SPA
This commit is contained in:
parent
c51dd48a73
commit
937b9fb48f
9 changed files with 180 additions and 90 deletions
|
|
@ -8,23 +8,73 @@ No permission is granted to copy, modify, distribute, or create derivative works
|
|||
|
||||
export module Catcrafts:Blog_impl;
|
||||
import :Blog;
|
||||
import :Root;
|
||||
import :Views;
|
||||
import std;
|
||||
|
||||
namespace Catcrafts {
|
||||
std::string RenderBlog() {
|
||||
using namespace Crafter::CppDOMBindings;
|
||||
|
||||
export namespace Catcrafts {
|
||||
std::vector<HtmlElementView>* blogButtons = new std::vector<HtmlElementView>();
|
||||
|
||||
void RenderBlog() {
|
||||
delete blogButtons;
|
||||
blogButtons = new std::vector<HtmlElementView>();
|
||||
std::string html = "";
|
||||
for(const BlogPost& post : *posts) {
|
||||
// For preview, we'll limit the content to first 200 characters
|
||||
std::string previewContent = post.content;
|
||||
if(previewContent.length() > 200) {
|
||||
// Find the last space before 200 characters to avoid cutting words
|
||||
std::size_t lastSpace = previewContent.find_last_of(' ', 200);
|
||||
if(lastSpace != std::string::npos) {
|
||||
previewContent = previewContent.substr(0, lastSpace) + "...";
|
||||
} else {
|
||||
previewContent = previewContent.substr(0, 200) + "...";
|
||||
}
|
||||
}
|
||||
html += std::format(R"(
|
||||
<div class="post fade-in">
|
||||
<div class="post-header">
|
||||
<h2 class="post-title">{}</h2>
|
||||
<h2 class="post-title"><a>{}</a></h2>
|
||||
<span class="post-date">{}</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
{}
|
||||
</div>
|
||||
</div>)", post.name, post.date, post.content);
|
||||
<div class="post-footer">
|
||||
<a id="blog-button-{}" class="btn">Read Full Post</a>
|
||||
</div>
|
||||
</div>)", post.name, post.date, previewContent, post.slug);
|
||||
}
|
||||
return html;
|
||||
main->SetInnerHTML(html);
|
||||
|
||||
for(const BlogPost& post : *posts) {
|
||||
HtmlElementView& view = blogButtons->emplace_back(std::format("blog-button-{}", post.slug));
|
||||
view.AddClickListener([slug = post.slug](Crafter::MouseEvent e) {
|
||||
PushState("{}", "", std::format("/blog/{}", slug));
|
||||
RenderRoot(std::format("/blog/{}", slug));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBlogPost(const std::string_view slug) {
|
||||
for(const BlogPost& post : *posts) {
|
||||
if(post.slug == slug) {
|
||||
main->SetInnerHTML(std::format(R"(
|
||||
<div class="post fade-in">
|
||||
<div class="post-header">
|
||||
<h1 class="post-title">{}</h1>
|
||||
<span class="post-date">{}</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
{}
|
||||
</div>
|
||||
</div>)", post.name, post.date, post.content));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
main->SetInnerHTML("<h1>Post Not Found</h1><p>The requested blog post could not be found.</p>");
|
||||
}
|
||||
}
|
||||
38
implementations/Catcrafts-Root.cpp
Normal file
38
implementations/Catcrafts-Root.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
catcrafts.net
|
||||
Copyright (C) 2025 Catcrafts
|
||||
|
||||
The source code of this website is made available for viewing purposes only.
|
||||
No permission is granted to copy, modify, distribute, or create derivative works.
|
||||
*/
|
||||
|
||||
export module Catcrafts:Root_impl;
|
||||
import :Root;
|
||||
import :Views;
|
||||
import :Blog;
|
||||
import std;
|
||||
|
||||
namespace Catcrafts {
|
||||
void RenderRoot(const std::string_view route) {
|
||||
std::string currentRoute = std::string(route);
|
||||
|
||||
if(currentRoute == "/blog" || currentRoute == "/") {
|
||||
RenderBlog();
|
||||
} else if(currentRoute.rfind("/blog/", 0) == 0) {
|
||||
// Handle individual blog post routes like /blog/0, /blog/1, etc.
|
||||
std::size_t pos = currentRoute.find_last_of('/');
|
||||
std::cout << pos << std::endl;
|
||||
std::cout << std::string::npos << std::endl;
|
||||
std::cout << (pos != std::string::npos) << std::endl;
|
||||
if(pos != std::string::npos) {
|
||||
std::string postSlug = currentRoute.substr(pos + 1);
|
||||
std::cout << postSlug << std::endl;
|
||||
RenderBlogPost(postSlug);
|
||||
} else {
|
||||
main->SetInnerHTML("<h1>Post Not Found</h1><p>The requested blog post could not be found.</p>");
|
||||
}
|
||||
} else {
|
||||
RenderBlog(); //default route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,27 +15,6 @@ using namespace Crafter::CppDOMBindings;
|
|||
|
||||
HtmlElementView* blogButton;
|
||||
|
||||
void RenderRoot(const std::string_view route) {
|
||||
std::string pageContent;
|
||||
if(route == "/blog") {
|
||||
pageContent = RenderBlog();
|
||||
} else {
|
||||
pageContent = RenderBlog(); //default route
|
||||
}
|
||||
// Set body content
|
||||
main->SetInnerHTML(pageContent);
|
||||
|
||||
// Update active nav link
|
||||
// auto navLinks = document->GetElementsByClassName("nav-container")[0]->GetElementsByTagName("a");
|
||||
// for(auto link : navLinks) {
|
||||
// if(link->GetAttribute("id") == "blog-nav-button") {
|
||||
// link->SetAttribute("class", "active");
|
||||
// } else {
|
||||
// link->SetAttribute("class", "");
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
int main() {
|
||||
AddPopStateListener([]() {
|
||||
RenderRoot(GetPathNameString());
|
||||
|
|
@ -44,7 +23,7 @@ int main() {
|
|||
blogButton = new HtmlElementView("blog-nav-button");
|
||||
blogButton->AddClickListener([](Crafter::MouseEvent e) {
|
||||
PushState("{}", "", "/blog");
|
||||
RenderRoot("blog");
|
||||
RenderRoot("/blog");
|
||||
});
|
||||
|
||||
RenderRoot("/");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue