<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Maori-English AI Chat Interface</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #4f46e5;
--primary-dark: #4338ca;
--secondary: #10b981;
--dark: #1e293b;
--darker: #0f172a;
--light: #f1f5f9;
--gray: #94a3b8;
--border: #cbd5e1;
--user-msg: #dbeafe;
--ai-msg: #f8fafc;
--error: #ef4444;
--success: #22c55e;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}
body {
background: linear-gradient(135deg, #0f172a, #1e293b);
color: var(--light);
height: 100vh;
display: flex;
flex-direction: column;
}
.chat-container {
display: flex;
flex-direction: column;
height: 100vh;
max-width: 1400px;
margin: 0 auto;
width: 100%;
}
header {
background: var(--darker);
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 1.5rem;
font-weight: 700;
}
.logo i {
color: var(--primary);
}
.user-controls {
display: flex;
gap: 1rem;
align-items: center;
}
.api-key-container {
position: relative;
}
.api-key-input {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
border: 1px solid var(--border);
background: var(--dark);
color: white;
width: 250px;
}
.api-key-btn {
background: var(--primary);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
cursor: pointer;
transition: background 0.3s;
}
.sidebar-toggle {
background: var(--dark);
border: none;
color: white;
padding: 0.5rem;
border-radius: 0.5rem;
cursor: pointer;
display: none;
margin-bottom: 1rem;
}
.sidebar {
width: 250px;
background: var(--darker);
border-right: 1px solid var(--border);
padding: 1rem;
display: flex;
flex-direction: column;
gap: 1rem;
transition: transform 0.3s ease;
}
.sidebar.collapsed {
transform: translateX(-100%);
position: absolute;
}
@media (max-width: 768px) {
.sidebar-toggle {
display: block;
}
.sidebar {
position: absolute;
z-index: 10;
height: calc(100% - 120px);
transform: translateX(-100%);
}
.sidebar.expanded {
transform: translateX(0);
}
}
.api-key-btn:hover {
background: var(--primary-dark);
}
.tools-dropdown {
position: relative;
}
.tools-btn {
background: var(--secondary);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: background 0.3s;
}
.tools-btn:hover {
background: #0da271;
}
.tools-menu {
position: absolute;
top: 100%;
right: 0;
background: var(--darker);
border: 1px solid var(--border);
border-radius: 0.5rem;
width: 300px;
margin-top: 0.5rem;
z-index: 100;
display: none;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.tools-menu.active {
display: block;
}
.tool-section {
padding: 1rem;
border-bottom: 1px solid var(--border);
}
.tool-section:last-child {
border-bottom: none;
}
.tool-section h3 {
margin-bottom: 0.75rem;
color: var(--secondary);
display: flex;
align-items: center;
gap: 0.5rem;
}
.tool-section select, .tool-section input, .tool-section textarea {
width: 100%;
padding: 0.75rem;
border-radius: 0.5rem;
border: 1px solid var(--border);
background: var(--dark);
color: white;
margin-bottom: 0.5rem;
}
.tool-section button {
width: 100%;
padding: 0.75rem;
border-radius: 0.5rem;
border: none;
background: var(--primary);
color: white;
cursor: pointer;
transition: background 0.3s;
margin-top: 0.5rem;
}
.tool-section button:hover {
background: var(--primary-dark);
}
.chat-area {
display: flex;
flex: 1;
overflow: hidden;
}
.sidebar {
width: 250px;
background: var(--darker);
border-right: 1px solid var(--border);
padding: 1rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.sidebar-section {
background: var(--dark);
border-radius: 0.75rem;
padding: 1rem;
}
.sidebar-section h3 {
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.file-list {
display: flex;
flex-direction: column;
gap: 0.5rem;
max-height: 200px;
overflow-y: auto;
}
.file-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 0.5rem;
}
.file-item button {
background: none;
border: none;
color: var(--gray);
cursor: pointer;
}
.file-item button:hover {
color: var(--secondary);
}
.upload-container {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.upload-btn {
background: var(--secondary);
color: white;
border: none;
padding: 0.75rem;
border-radius: 0.5rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
transition: background 0.3s;
}
.upload-btn:hover {
background: #0da271;
}
.upload-btn i {
font-size: 1.2rem;
}
.chat-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 1.5rem;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.message {
max-width: 80%;
padding: 1rem 1.5rem;
border-radius: 1rem;
line-height: 1.5;
position: relative;
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.user-message {
background: var(--user-msg);
color: var(--dark);
align-self: flex-end;
border-bottom-right-radius: 0;
}
.ai-message {
background: var(--ai-msg);
color: var(--dark);
align-self: flex-start;
border-bottom-left-radius: 0;
}
.message-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.5rem;
font-weight: 600;
}
.user-message .message-header {
color: var(--primary-dark);
}
.ai-message .message-header {
color: var(--secondary);
}
.input-container {
padding: 1.5rem;
background: var(--darker);
border-top: 1px solid var(--border);
display: flex;
gap: 1rem;
}
.message-input {
flex: 1;
padding: 1rem 1.5rem;
border-radius: 2rem;
border: 1px solid var(--border);
background: var(--dark);
color: white;
font-size: 1rem;
resize: none;
min-height: 60px;
max-height: 150px;
}
.send-btn {
background: var(--primary);
color: white;
border: none;
border-radius: 50%;
width: 60px;
height: 60px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s;
align-self: flex-end;
margin-bottom: 5px;
}
.send-btn:hover {
background: var(--primary-dark);
}
.send-btn i {
font-size: 1.5rem;
}
.status-bar {
padding: 0.5rem 1.5rem;
background: var(--dark);
border-top: 1px solid var(--border);
display: flex;
justify-content: space-between;
font-size: 0.875rem;
color: var(--gray);
}
/* Responsive design */
@media (max-width: 768px) {
.chat-area {
flex-direction: column;
}
.sidebar {
width: 100%;
border-right: none;
border-bottom: 1px solid var(--border);
max-height: 200px;
}
.message {
max-width: 90%;
}
.api-key-input {
width: 150px;
}
.tools-menu {
width: 250px;
}
}
@media (max-width: 480px) {
header {
flex-direction: column;
gap: 1rem;
}
.user-controls {
width: 100%;
justify-content: space-between;
}
.api-key-input {
width: 100%;
}
.input-container {
padding: 1rem;
}
.message-input {
padding: 0.75rem 1rem;
}
.send-btn {
width: 50px;
height: 50px;
}
}
/* Scrollbar styling */
.messages-container::-webkit-scrollbar, .file-list::-webkit-scrollbar {
width: 8px;
}
.messages-container::-webkit-scrollbar-track, .file-list::-webkit-scrollbar-track {
background: var(--darker);
}
.messages-container::-webkit-scrollbar-thumb, .file-list::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 4px;
}
.messages-container::-webkit-scrollbar-thumb:hover, .file-list::-webkit-scrollbar-thumb:hover {
background: var(--primary-dark);
}
/* Loading indicator */
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(255,255,255,.3);
border-radius: 50%;
border-top-color: var(--primary);
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.typing-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background: var(--ai-msg);
border-radius: 1rem;
align-self: flex-start;
margin-bottom: 1.5rem;
color: var(--dark);
}
.typing-indicator span {
height: 8px;
width: 8px;
background: var(--gray);
border-radius: 50%;
display: inline-block;
animation: bounce 1.3s linear infinite;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.15s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.3s;
}
@keyframes bounce {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-5px); }
}
</style>
</head>
<body>
<div class="chat-container">
<header>
<div class="logo">
<i class="fas fa-robot"></i>
<span>Maori-English AI Assistant</span>
</div>
<div class="user-controls">
<button class="sidebar-toggle" id="sidebarToggle">
<i class="fas fa-bars"></i> Toggle Sidebar
</button>
<div class="api-key-container">
<input type="text" class="api-key-input" id="apiKeyInput" placeholder="Enter your API key">
<button class="api-key-btn" id="saveApiKeyBtn">Save Key</button>
</div>
<div class="tools-dropdown">
<button class="tools-btn" id="toolsDropdownBtn">
<i class="fas fa-tools"></i>
AI Tools
</button>
<div class="tools-menu" id="toolsMenu">
<div class="tool-section">
<h3><i class="fas fa-language"></i> Maori-English Translation</h3>
<select id="translateDirection">
<option value="englishToMaori">English to Maori</option>
<option value="maoriToEnglish">Maori to English</option>
</select>
<textarea id="translateText" placeholder="Enter text to translate"></textarea>
<button id="translateBtn">Translate</button>
</div>
<div class="tool-section">
<h3><i class="fas fa-book"></i> Story Generation</h3>
<select id="storyType">
<option value="traditional">Traditional Maori Stories</option>
<option value="modern">Modern Maori Stories</option>
<option value="educational">Educational Stories</option>
</select>
<input type="text" id="storyLength" placeholder="Word count (e.g., 200)">
<textarea id="storyPrompt" placeholder="Enter a story prompt or theme"></textarea>
<button id="generateStoryBtn">Generate Story</button>
</div>
<div class="tool-section">
<h3><i class="fas fa-tree"></i> Pepeha Creation</h3>
<input type="text" id="mountainName" placeholder="Your mountain (Maunga)">
<input type="text" id="riverName" placeholder="Your river (Awa)">
<input type="text" id="tribeName" placeholder="Your tribe (Iwi)">
<button id="createPepehaBtn">Create Pepeha</button>
</div>
<div class="tool-section">
<h3><i class="fas fa-people-arrows"></i> Whakapapa Learning</h3>
<select id="whakapapaTopic">
<option value="genealogy">Genealogy Structure</option>
<option value="ancestry">Ancestry Research</option>
<option value="familyTree">Family Tree Building</option>
</select>
<textarea id="whakapapaQuery" placeholder="Enter your query or name to research"></textarea>
<button id="whakapapaBtn">Learn & Explore</button>
</div>
</div>
</div>
</div>
</header>
<div class="chat-area">
<div class="sidebar" id="sidebar">
<div class="sidebar-section">
<h3><i class="fas fa-file-upload"></i> Uploads</h3>
<div class="upload-container">
<button class="upload-btn" id="uploadBtn">
<i class="fas fa-cloud-upload-alt"></i>
Upload File
</button>
<input type="file" id="fileInput" style="display: none;">
</div>
</div>
<div class="sidebar-section">
<h3><i class="fas fa-file-download"></i> Downloads</h3>
<div class="file-list" id="fileList">
<div class="file-item">
<span>maori_greetings.pdf</span>
<button><i class="fas fa-download"></i></button>
</div>
<div class="file-item">
<span>pepeha_examples.docx</span>
<button><i class="fas fa-download"></i></button>
</div>
<div class="file-item">
<span>whakapapa_guide.xlsx</span>
<button><i class="fas fa-download"></i></button>
</div>
</div>
</div>
<div class="sidebar-section">
<h3><i class="fas fa-user-cog"></i> User Tools</h3>
<div class="upload-container">
<button class="upload-btn" id="historyBtn">
<i class="fas fa-history"></i>
Chat History
</button>
<button class="upload-btn" id="settingsBtn">
<i class="fas fa-cog"></i>
Settings
</button>
</div>
</div>
</div>
<div class="chat-content">
<div class="messages-container" id="messagesContainer">
<div class="message ai-message">
<div class="message-header">
<i class="fas fa-robot"></i>
<span>AI Assistant</span>
</div>
<div class="message-content">
Kia ora! I'm your Maori-English AI assistant. I can help you translate between Maori and English, generate Maori stories, create pepeha, and explore whakapapa. How can I assist you today?
</div>
</div>
<div class="message user-message">
<div class="message-header">
<i class="fas fa-user"></i>
<span>You</span>
</div>
<div class="message-content">
Can you translate "Hello, how are you?" to Maori?
</div>
</div>
<div class="message ai-message">
<div class="message-header">
<i class="fas fa-robot"></i>
<span>AI Assistant</span>
</div>
<div class="message-content">
Kia ora! Kei te pēhea koe?
</div>
</div>
<div class="typing-indicator" id="typingIndicator" style="display: none;">
<span></span>
<span></span>
<span></span>
<span>AI is thinking...</span>
</div>
</div>
<div class="input-container">
<textarea class="message-input" id="messageInput" placeholder="Type your message here..."></textarea>
<button class="send-btn" id="sendBtn">
<i class="fas fa-paper-plane"></i>
</button>
</div>
<div class="status-bar">
<div>Connected to AI service</div>
<div>Messages: 3</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const apiKeyInput = document.getElementById('apiKeyInput');
const saveApiKeyBtn = document.getElementById('saveApiKeyBtn');
const toolsDropdownBtn = document.getElementById('toolsDropdownBtn');
const toolsMenu = document.getElementById('toolsMenu');
const messageInput = document.getElementById('messageInput');
const sendBtn = document.getElementById('sendBtn');
const messagesContainer = document.getElementById('messagesContainer');
const fileInput = document.getElementById('fileInput');
const uploadBtn = document.getElementById('uploadBtn');
const typingIndicator = document.getElementById('typingIndicator');
const sidebar = document.getElementById('sidebar');
const sidebarToggle = document.getElementById('sidebarToggle');
// Set default API key
const defaultApiKey = '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';
apiKeyInput.value = defaultApiKey;
localStorage.setItem('aiChatApiKey', defaultApiKey);
// Toggle sidebar on mobile
sidebarToggle.addEventListener('click', function() {
sidebar.classList.toggle('expanded');
});
// Toggle tools dropdown
toolsDropdownBtn.addEventListener('click', function() {
toolsMenu.classList.toggle('active');
});
// Close dropdown when clicking outside
document.addEventListener('click', function(e) {
if (!toolsDropdownBtn.contains(e.target) && !toolsMenu.contains(e.target)) {
toolsMenu.classList.remove('active');
}
});
// Send message functionality
sendBtn.addEventListener('click', sendMessage);
messageInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
// File upload functionality
uploadBtn.addEventListener('click', function() {
fileInput.click();
});
fileInput.addEventListener('change', function(e) {
if (e.target.files.length > 0) {
const file = e.target.files[0];
addFileToList(file.name);
showNotification(`File uploaded: ${file.name}`, 'success');
}
});
// AI Tool Buttons
document.getElementById('translateBtn').addEventListener('click', function() {
const direction = document.getElementById('translateDirection').value;
const text = document.getElementById('translateText').value.trim();
if (text) {
processTool('translate', { direction, text });
} else {
showNotification('Please enter text to translate', 'error');
}
});
document.getElementById('generateStoryBtn').addEventListener('click', function() {
const type = document.getElementById('storyType').value;
const length = document.getElementById('storyLength').value;
const prompt = document.getElementById('storyPrompt').value.trim();
processTool('story', { type, length, prompt });
});
document.getElementById('createPepehaBtn').addEventListener('click', function() {
const mountain = document.getElementById('mountainName').value.trim();
const river = document.getElementById('riverName').value.trim();
const tribe = document.getElementById('tribeName').value.trim();
processTool('pepeha', { mountain, river, tribe });
});
document.getElementById('whakapapaBtn').addEventListener('click', function() {
const topic = document.getElementById('whakapapaTopic').value;
const query = document.getElementById('whakapapaQuery').value.trim();
if (query) {
processTool('whakapapa', { topic, query });
} else {
showNotification('Please enter a query for whakapapa research', 'error');
}
});
function sendMessage() {
const message = messageInput.value.trim();
if (!message) return;
addMessage(message, 'user');
messageInput.value = '';
// Show typing indicator
typingIndicator.style.display = 'flex';
messagesContainer.scrollTop = messagesContainer.scrollHeight;
// Simulate AI response delay
setTimeout(() => {
typingIndicator.style.display = 'none';
addMessage("I've received your message. This is a simulated response for general chat.", 'ai');
}, 2000);
}
function addMessage(content, sender) {
const messageDiv = document.createElement('div');
messageDiv.classList.add('message');
messageDiv.classList.add(sender === 'user' ? 'user-message' : 'ai-message');
const headerDiv = document.createElement('div');
headerDiv.classList.add('message-header');
headerDiv.innerHTML = sender === 'user'
? `<i class="fas fa-user"></i> <span>You</span>`
: `<i class="fas fa-robot"></i> <span>AI Assistant</span>`;
const contentDiv = document.createElement('div');
contentDiv.classList.add('message-content');
contentDiv.textContent = content;
messageDiv.appendChild(headerDiv);
messageDiv.appendChild(contentDiv);
messagesContainer.appendChild(messageDiv);
// Scroll to bottom
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
function addFileToList(filename) {
const fileList = document.getElementById('fileList');
const fileItem = document.createElement('div');
fileItem.classList.add('file-item');
fileItem.innerHTML = `
<span>${filename}</span>
<button><i class="fas fa-download"></i></button>
`;
fileList.appendChild(fileItem);
// Add download functionality
fileItem.querySelector('button').addEventListener('click', function() {
showNotification(`Downloading ${filename}...`, 'success');
});
}
function processTool(toolName, params) {
// Show typing indicator
typingIndicator.style.display = 'flex';
messagesContainer.scrollTop = messagesContainer.scrollHeight;
// Close dropdown menu
toolsMenu.classList.remove('active');
// Get API key
const apiKey = localStorage.getItem('aiChatApiKey');
if (!apiKey) {
setTimeout(() => {
typingIndicator.style.display = 'none';
showNotification('Please set your API key first', 'error');
}, 1000);
return;
}
// Simulate AI tool processing with specific responses
setTimeout(() => {
typingIndicator.style.display = 'none';
let response = '';
switch(toolName) {
case 'translate':
if (params.direction === 'englishToMaori') {
response = `Translation to Maori: [Simulated Maori translation of "${params.text}"]`;
} else {
response = `Translation to English: [Simulated English translation of "${params.text}"]`;
}
break;
case 'story':
response = `Generated ${params.type} story (${params.length || 'variable'} words): [Simulated Maori story based on "${params.prompt}"]`;
break;
case 'pepeha':
response = `Your Pepeha:\nKo ${params.mountain || '[mountain]'} taku maunga\nKo ${params.river || '[river]'} taku awa\nKo ${params.tribe || '[tribe]'} taku iwi\nTēnā koe!`;
break;
case 'whakapapa':
response = `Whakapapa Information for "${params.query}": [Simulated genealogy information based on ${params.topic}]`;
break;
default:
response = "Tool processed successfully";
}
addMessage(response, 'ai');
}, 3000);
}
function showNotification(message, type) {
const notification = document.createElement('div');
notification.textContent = message;
notification.style.position = 'fixed';
notification.style.bottom = '20px';
notification.style.right = '20px';
notification.style.padding = '10px 20px';
notification.style.borderRadius = '5px';
notification.style.color = 'white';
notification.style.zIndex = '1000';
notification.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
notification.style.animation = 'fadeIn 0.3s, fadeOut 0.3s 2.7s';
notification.style.background = type === 'error' ? 'var(--error)' : 'var(--success)';
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
}
// Add CSS for notification animations
const styleSheet = document.createElement('style');
styleSheet.textContent = `
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeOut {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(20px); }
}
`;
document.head.appendChild(styleSheet);
});
</script>
</body>
</html>