mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-21 11:18:08 +00:00
Enhance notes panel with search, categories, and improved UI
This commit is contained in:
272
index.html
272
index.html
@@ -114,22 +114,23 @@
|
||||
position: fixed;
|
||||
bottom: 80px;
|
||||
right: 20px;
|
||||
width: 300px;
|
||||
max-height: 400px;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
width: 350px;
|
||||
max-height: 500px;
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.5);
|
||||
z-index: 1999;
|
||||
font-family: Arial, sans-serif;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
#notes-header {
|
||||
background-color: #222;
|
||||
padding: 10px 15px;
|
||||
padding: 12px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@@ -138,18 +139,66 @@
|
||||
|
||||
#notes-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
#notes-close {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
color: #aaa;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
#notes-close:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#notes-search-container {
|
||||
padding: 10px 15px;
|
||||
background-color: #333;
|
||||
border-bottom: 1px solid #444;
|
||||
}
|
||||
|
||||
#notes-search {
|
||||
width: 100%;
|
||||
padding: 8px 10px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
background-color: #222;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#notes-search:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.5);
|
||||
}
|
||||
|
||||
#notes-categories {
|
||||
display: flex;
|
||||
padding: 5px 15px;
|
||||
background-color: #2c2c2c;
|
||||
border-bottom: 1px solid #444;
|
||||
}
|
||||
|
||||
.notes-category {
|
||||
padding: 5px 10px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.notes-category.active {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.notes-category:hover:not(.active) {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
#notes-content {
|
||||
padding: 15px;
|
||||
@@ -161,6 +210,14 @@
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #444;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.note-item:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.note-item:last-child {
|
||||
@@ -174,20 +231,47 @@
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
color: #3498db;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.note-icons {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.note-icon {
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.note-text {
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
max-height: 80px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s;
|
||||
}
|
||||
|
||||
.note-item.expanded .note-text {
|
||||
max-height: 1000px;
|
||||
}
|
||||
|
||||
.note-timestamp {
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
margin-top: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#notes-toggle {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
@@ -197,7 +281,7 @@
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||
z-index: 1998;
|
||||
font-size: 24px;
|
||||
font-size: 28px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
@@ -213,9 +297,9 @@
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 12px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -322,9 +406,17 @@
|
||||
<!-- Notes Panel -->
|
||||
<div id="notes-panel">
|
||||
<div id="notes-header">
|
||||
<div id="notes-title">Notes</div>
|
||||
<div id="notes-title">Notes & Information</div>
|
||||
<div id="notes-close">×</div>
|
||||
</div>
|
||||
<div id="notes-search-container">
|
||||
<input type="text" id="notes-search" placeholder="Search notes...">
|
||||
</div>
|
||||
<div id="notes-categories">
|
||||
<div class="notes-category active" data-category="all">All</div>
|
||||
<div class="notes-category" data-category="important">Important</div>
|
||||
<div class="notes-category" data-category="unread">Unread</div>
|
||||
</div>
|
||||
<div id="notes-content"></div>
|
||||
</div>
|
||||
<div id="notes-toggle">
|
||||
@@ -469,9 +561,31 @@
|
||||
// Update the notes panel with current notes
|
||||
function updateNotesPanel() {
|
||||
const notesContent = document.getElementById('notes-content');
|
||||
const searchTerm = document.getElementById('notes-search')?.value?.toLowerCase() || '';
|
||||
|
||||
// Get active category
|
||||
const activeCategory = document.querySelector('.notes-category.active')?.dataset.category || 'all';
|
||||
|
||||
// Filter notes based on search and category
|
||||
let filteredNotes = [...gameNotes];
|
||||
|
||||
// Apply category filter
|
||||
if (activeCategory === 'important') {
|
||||
filteredNotes = filteredNotes.filter(note => note.important);
|
||||
} else if (activeCategory === 'unread') {
|
||||
filteredNotes = filteredNotes.filter(note => !note.read);
|
||||
}
|
||||
|
||||
// Apply search filter
|
||||
if (searchTerm) {
|
||||
filteredNotes = filteredNotes.filter(note =>
|
||||
note.title.toLowerCase().includes(searchTerm) ||
|
||||
note.text.toLowerCase().includes(searchTerm)
|
||||
);
|
||||
}
|
||||
|
||||
// Sort notes with important ones first, then by timestamp (newest first)
|
||||
const sortedNotes = [...gameNotes].sort((a, b) => {
|
||||
filteredNotes.sort((a, b) => {
|
||||
if (a.important !== b.important) {
|
||||
return a.important ? -1 : 1;
|
||||
}
|
||||
@@ -482,29 +596,48 @@
|
||||
notesContent.innerHTML = '';
|
||||
|
||||
// Add notes
|
||||
if (sortedNotes.length === 0) {
|
||||
notesContent.innerHTML = '<div class="note-item">No notes yet.</div>';
|
||||
if (filteredNotes.length === 0) {
|
||||
if (searchTerm) {
|
||||
notesContent.innerHTML = '<div class="note-item">No notes match your search.</div>';
|
||||
} else if (activeCategory !== 'all') {
|
||||
notesContent.innerHTML = `<div class="note-item">No ${activeCategory} notes found.</div>`;
|
||||
} else {
|
||||
notesContent.innerHTML = '<div class="note-item">No notes yet.</div>';
|
||||
}
|
||||
} else {
|
||||
sortedNotes.forEach(note => {
|
||||
filteredNotes.forEach(note => {
|
||||
const noteElement = document.createElement('div');
|
||||
noteElement.className = 'note-item';
|
||||
noteElement.dataset.id = note.id;
|
||||
|
||||
let noteContent = `<div class="note-title">`;
|
||||
// Format the timestamp
|
||||
const timestamp = new Date(note.timestamp);
|
||||
const formattedDate = timestamp.toLocaleDateString();
|
||||
const formattedTime = timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
|
||||
let noteContent = `<div class="note-title">
|
||||
<span>${note.title}</span>
|
||||
<div class="note-icons">`;
|
||||
|
||||
if (note.important) {
|
||||
noteContent += `⭐ `;
|
||||
noteContent += `<span class="note-icon">⭐</span>`;
|
||||
}
|
||||
if (!note.read) {
|
||||
noteContent += `📌 `;
|
||||
noteContent += `<span class="note-icon">📌</span>`;
|
||||
}
|
||||
noteContent += `${note.title}</div>`;
|
||||
|
||||
noteContent += `</div></div>`;
|
||||
noteContent += `<div class="note-text">${note.text}</div>`;
|
||||
noteContent += `<div class="note-timestamp">${formattedDate} ${formattedTime}</div>`;
|
||||
|
||||
noteElement.innerHTML = noteContent;
|
||||
|
||||
// Mark as read when clicked
|
||||
// Toggle expanded state when clicked
|
||||
noteElement.addEventListener('click', () => {
|
||||
if (!note.read) {
|
||||
noteElement.classList.toggle('expanded');
|
||||
|
||||
// Mark as read when expanded
|
||||
if (!note.read && noteElement.classList.contains('expanded')) {
|
||||
note.read = true;
|
||||
updateNotesCount();
|
||||
updateNotesPanel();
|
||||
@@ -531,15 +664,6 @@
|
||||
const isVisible = notesPanel.style.display === 'block';
|
||||
|
||||
notesPanel.style.display = isVisible ? 'none' : 'block';
|
||||
|
||||
// Mark all as read when panel is opened
|
||||
if (!isVisible) {
|
||||
gameNotes.forEach(note => {
|
||||
note.read = true;
|
||||
});
|
||||
updateNotesCount();
|
||||
updateNotesPanel();
|
||||
}
|
||||
}
|
||||
|
||||
// Replace alert with our custom notification system
|
||||
@@ -640,6 +764,23 @@
|
||||
const notesClose = document.getElementById('notes-close');
|
||||
notesClose.addEventListener('click', toggleNotesPanel);
|
||||
|
||||
// Set up search functionality
|
||||
const notesSearch = document.getElementById('notes-search');
|
||||
notesSearch.addEventListener('input', updateNotesPanel);
|
||||
|
||||
// Set up category filters
|
||||
const categories = document.querySelectorAll('.notes-category');
|
||||
categories.forEach(category => {
|
||||
category.addEventListener('click', () => {
|
||||
// Remove active class from all categories
|
||||
categories.forEach(c => c.classList.remove('active'));
|
||||
// Add active class to clicked category
|
||||
category.classList.add('active');
|
||||
// Update notes panel
|
||||
updateNotesPanel();
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize notes count
|
||||
updateNotesCount();
|
||||
});
|
||||
@@ -2058,32 +2199,59 @@
|
||||
|
||||
// Add readable text as a note
|
||||
if (data.text.trim().length > 0) {
|
||||
addNote(data.name, data.text);
|
||||
addNote(data.name, data.text, data.important || false);
|
||||
|
||||
// Show notification about adding to notes
|
||||
gameAlert(`Added "${data.name}" to your notes.`, 'info', 'Note Added', 3000);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.takeable) {
|
||||
message += `This item can be taken\n\n`;
|
||||
// If it's a note type item that's already been read and added to notes,
|
||||
// don't add it to inventory unless it has a special purpose
|
||||
const isJustInformationalNote =
|
||||
data.type === 'notes' &&
|
||||
data.readable &&
|
||||
data.text &&
|
||||
!data.hasSpecialPurpose; // Add this flag to notes that need to be in inventory
|
||||
|
||||
if (!inventory || !Array.isArray(inventory.items)) {
|
||||
console.error('Inventory not properly initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
const isInRoom = currentRoom &&
|
||||
rooms[currentRoom] &&
|
||||
rooms[currentRoom].objects &&
|
||||
rooms[currentRoom].objects[sprite.name];
|
||||
if (!isJustInformationalNote) {
|
||||
message += `This item can be taken\n\n`;
|
||||
|
||||
if (!inventory || !Array.isArray(inventory.items)) {
|
||||
console.error('Inventory not properly initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
const isInRoom = currentRoom &&
|
||||
rooms[currentRoom] &&
|
||||
rooms[currentRoom].objects &&
|
||||
rooms[currentRoom].objects[sprite.name];
|
||||
|
||||
const itemIdentifier = createItemIdentifier(sprite.scenarioData);
|
||||
|
||||
const isInInventory = inventory.items.some(item =>
|
||||
item && createItemIdentifier(item.scenarioData) === itemIdentifier
|
||||
);
|
||||
|
||||
if (isInRoom && !isInInventory) {
|
||||
console.log('Adding item to inventory:', itemIdentifier);
|
||||
addToInventory(sprite);
|
||||
}
|
||||
} else {
|
||||
// For informational notes, just remove them from the room after reading
|
||||
if (currentRoom &&
|
||||
rooms[currentRoom] &&
|
||||
rooms[currentRoom].objects &&
|
||||
rooms[currentRoom].objects[sprite.name]) {
|
||||
|
||||
const itemIdentifier = createItemIdentifier(sprite.scenarioData);
|
||||
const roomObj = rooms[currentRoom].objects[sprite.name];
|
||||
roomObj.setVisible(false);
|
||||
roomObj.active = false;
|
||||
|
||||
const isInInventory = inventory.items.some(item =>
|
||||
item && createItemIdentifier(item.scenarioData) === itemIdentifier
|
||||
);
|
||||
|
||||
if (isInRoom && !isInInventory) {
|
||||
console.log('Adding item to inventory:', itemIdentifier);
|
||||
addToInventory(sprite);
|
||||
// Show notification about adding to notes instead of inventory
|
||||
gameAlert(`Information recorded in your notes.`, 'success', 'Note Recorded', 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user