website example
This commit is contained in:
parent
c6c62e5852
commit
c4f764e4ce
6 changed files with 198 additions and 182 deletions
|
|
@ -12,7 +12,8 @@ struct Note {
|
|||
void RenderNotes();
|
||||
|
||||
// Global vector to store notes
|
||||
std::vector<Note> notes;
|
||||
std::vector<Note>* notes = new std::vector<Note>();
|
||||
std::vector<HtmlElementView>* noteButtons = new std::vector<HtmlElementView>();
|
||||
|
||||
// Create the head section
|
||||
HtmlElementView* head = new HtmlElementView("head", R"(
|
||||
|
|
@ -20,16 +21,22 @@ HtmlElementView* head = new HtmlElementView("head", R"(
|
|||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center; /* Horizontal centering */
|
||||
align-items: center; /* Vertical centering */
|
||||
}
|
||||
.app-container {
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
width: 50vw;
|
||||
max-width: 600px;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
|
|
@ -44,7 +51,6 @@ HtmlElementView* head = new HtmlElementView("head", R"(
|
|||
.input-section textarea {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
resize: vertical;
|
||||
|
|
@ -125,7 +131,6 @@ HtmlElementView* body = new HtmlElementView("body", R"(
|
|||
<button id="addNoteBtn">Add Note</button>
|
||||
</div>
|
||||
|
||||
<div id="error"></div>
|
||||
<div id="loading"></div>
|
||||
|
||||
<div class="notes-section">
|
||||
|
|
@ -136,121 +141,97 @@ HtmlElementView* body = new HtmlElementView("body", R"(
|
|||
)");
|
||||
HtmlElementView* addNoteBtn = new HtmlElementView("addNoteBtn");
|
||||
HtmlElementView* noteInput = new HtmlElementView("noteInput");
|
||||
HtmlElementView* loadingIndicator = new HtmlElementView("loading");
|
||||
HtmlElementView* notesContainer = new HtmlElementView("notesContainer");
|
||||
|
||||
// Function to fetch all notes from the backend
|
||||
void FetchNotes() {
|
||||
HtmlElementView loadingIndicator("loading");
|
||||
loadingIndicator.SetInnerHTML("<p>Loading notes...</p>");
|
||||
loadingIndicator->SetInnerHTML("<p>Loading notes...</p>");
|
||||
|
||||
// Make HTTP request to backend
|
||||
Fetch("http://localhost:3000/getNotes", [](std::string content) {
|
||||
// Parse response - each note is separated by \n\n
|
||||
notes.clear();
|
||||
|
||||
// Simple parsing of note data
|
||||
std::uint_fast32_t pos = 0;
|
||||
std::uint_fast32_t prevPos = 0;
|
||||
|
||||
while ((pos = content.find('\n', prevPos)) != std::string::npos) {
|
||||
if (pos > prevPos) {
|
||||
// Extract ID
|
||||
std::string idStr = content.substr(prevPos, pos - prevPos);
|
||||
std::uint_fast32_t id = std::stoul(idStr);
|
||||
|
||||
// Find the next newline for content
|
||||
std::uint_fast32_t contentStart = pos + 1;
|
||||
std::uint_fast32_t contentEnd = content.find('\n', contentStart);
|
||||
if (contentEnd != std::string::npos) {
|
||||
std::string noteContent = content.substr(contentStart, contentEnd - contentStart);
|
||||
notes.push_back({id, noteContent});
|
||||
}
|
||||
Fetch("http://localhost:3000/getNotes", [](std::string input) {
|
||||
notes->clear();
|
||||
std::istringstream stream(input);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(stream, line)) {
|
||||
// Skip empty lines
|
||||
if (line.empty()) continue;
|
||||
|
||||
// First line is ID
|
||||
std::uint32_t id = std::stoi(line);
|
||||
|
||||
// Read content until the next empty line
|
||||
std::string content;
|
||||
while (std::getline(stream, line) && !line.empty()) {
|
||||
if (!content.empty()) content += "\n"; // preserve line breaks
|
||||
content += line;
|
||||
}
|
||||
prevPos = content.find('\n', pos) + 1;
|
||||
if (prevPos >= content.length()) break;
|
||||
|
||||
notes->push_back(Note{id, content});
|
||||
}
|
||||
|
||||
// Update UI with notes
|
||||
//RenderNotes();
|
||||
loadingIndicator->SetInnerHTML("<p>Notes loaded!</p>");
|
||||
RenderNotes();
|
||||
});
|
||||
}
|
||||
|
||||
// Function to add a new note via the backend
|
||||
void AddNote(const std::string& content) {
|
||||
if (content.empty()) return;
|
||||
|
||||
HtmlElementView loadingIndicator("loading");
|
||||
loadingIndicator.SetInnerHTML("<p>Saving note...</p>");
|
||||
|
||||
// Make POST request to create note
|
||||
Fetch("http://localhost:3000/createNote", content, [](std::string content) {});
|
||||
}
|
||||
|
||||
// Function to delete a note via the backend
|
||||
void DeleteNote(std::uint32_t id) {
|
||||
HtmlElementView loadingIndicator("loading");
|
||||
loadingIndicator.SetInnerHTML("<p>Deleting note...</p>");
|
||||
loadingIndicator->SetInnerHTML("<p>Deleting note...</p>");
|
||||
|
||||
// Make POST request to delete note
|
||||
Fetch("http://localhost:3000/deleteNote", std::to_string(id), [](std::string content) {
|
||||
FetchNotes();
|
||||
loadingIndicator->SetInnerHTML("<p>Note deleted!</p>");
|
||||
});
|
||||
}
|
||||
|
||||
// Function to render all notes to the DOM
|
||||
void RenderNotes() {
|
||||
HtmlElementView notesContainer("notesContainer");
|
||||
|
||||
if (notes.empty()) {
|
||||
notesContainer.SetInnerHTML("<p>No notes yet. Add one below!</p>");
|
||||
if (notes->empty()) {
|
||||
notesContainer->SetInnerHTML("<p>No notes yet. Add one below!</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string html = "<div class='notes-list'>";
|
||||
for (const Note& note : notes) {
|
||||
noteButtons->clear();
|
||||
for (const Note& note : *notes) {
|
||||
html += std::format(
|
||||
R"(<div class='note-item' id='note-{}'>
|
||||
<div class='note-content'>{}</div>
|
||||
<button class='delete-btn' onclick='DeleteNote({})'>Delete</button>
|
||||
<button id="note-{}-delete" class='delete-btn'>Delete</button>
|
||||
</div>)",
|
||||
note.id, note.content, note.id
|
||||
);
|
||||
}
|
||||
html += "</div>";
|
||||
|
||||
notesContainer.SetInnerHTML(html);
|
||||
|
||||
// Add event listeners to delete buttons
|
||||
for (const Note& note : notes) {
|
||||
HtmlElementView deleteBtn(std::format("note-{}-delete", note.id));
|
||||
deleteBtn.AddClickListener([id = note.id](MouseEvent event) {
|
||||
notesContainer->SetInnerHTML(html);
|
||||
|
||||
for (const Note& note : *notes) {
|
||||
HtmlElementView& view = noteButtons->emplace_back(std::format("note-{}-delete", note.id));
|
||||
view.AddClickListener([id = note.id](MouseEvent event) {
|
||||
DeleteNote(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::string* currentNoteValue = new std::string();
|
||||
|
||||
// Main function
|
||||
int main() {
|
||||
// Initialize the app
|
||||
FetchNotes();
|
||||
|
||||
// Add input listener to track textarea changes
|
||||
noteInput->AddInputListener([&](InputEvent event) {
|
||||
*currentNoteValue += event.data;
|
||||
std::cout << *currentNoteValue << std::endl;
|
||||
});
|
||||
|
||||
// Add click listener to add note button
|
||||
addNoteBtn->AddClickListener([&](MouseEvent event) {
|
||||
std::cout << "click!" << std::endl;
|
||||
std::cout << *currentNoteValue << std::endl;
|
||||
// Use the captured value from input event
|
||||
if (!currentNoteValue->empty()) {
|
||||
AddNote(*currentNoteValue);
|
||||
// Clear the textarea by setting its value to empty string
|
||||
noteInput->SetInnerHTML("");
|
||||
*currentNoteValue = ""; // Reset the stored value
|
||||
}
|
||||
std::string noteValue = noteInput->GetValue();
|
||||
std::cout << noteValue << std::endl;
|
||||
if (!noteValue.empty()) {
|
||||
loadingIndicator->SetInnerHTML("<p>Saving note...</p>");
|
||||
Fetch("http://localhost:3000/createNote", noteValue, [¬eValue](std::string content) {
|
||||
notes->push_back({static_cast<std::uint32_t>(std::stoi(content)), noteValue});
|
||||
noteInput->SetValue("");
|
||||
RenderNotes();
|
||||
loadingIndicator->SetInnerHTML("<p>Saved note!</p>");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue