Switch hub endpoints to use the hub `name` slug and update frontend routes/clients accordingly. Backend: HubViewSet now uses lookup_field='name'; PostViewSet list supports `sort=top` with vote_score annotation and time windows/custom ranges, and a new TopPostsCursorPagination was added. Frontend: routes changed from `/hub/:id` to `/h/:name`, the generated hubs API was updated from id->name, and the hub feed client accepts `sort`, `time`, `start`, and `end` params (query key updated). Also adds new homepage UI components (HeroSection, DroneSection) and navbar improvements (scroll state, auto-close mobile menu on route changes, and small icon/class tweaks).
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import { useEffect } from "react";
|
|
import HeroSection from "@/components/home/hero/HeroSection";
|
|
import DroneSection from "@/components/home/drone/DroneSection";
|
|
import WebDevSection from "@/components/home/webdev/WebDevSection";
|
|
import ProjectsSection from "@/components/home/projects/ProjectsSection";
|
|
import TechMarquee from "@/components/home/tech/TechMarquee";
|
|
import ContactMeForm from "@/components/home/ContactMe/ContactMeForm";
|
|
|
|
export default function Home() {
|
|
// Spark cursor on click
|
|
useEffect(() => {
|
|
const handleClick = (event: MouseEvent) => {
|
|
const spark = document.createElement("div");
|
|
spark.className = "spark-cursor";
|
|
document.body.appendChild(spark);
|
|
spark.style.top = `${event.pageY}px`;
|
|
spark.style.left = `${event.pageX}px`;
|
|
for (let i = 0; i < 8; i++) {
|
|
const span = document.createElement("span");
|
|
span.style.transform = `rotate(${i * 45}deg)`;
|
|
spark.appendChild(span);
|
|
}
|
|
setTimeout(() => {
|
|
spark.querySelectorAll("span").forEach((s) => {
|
|
(s as HTMLElement).classList.add("animate");
|
|
});
|
|
}, 10);
|
|
setTimeout(() => spark.remove(), 1000);
|
|
};
|
|
document.body.addEventListener("click", handleClick);
|
|
return () => document.body.removeEventListener("click", handleClick);
|
|
}, []);
|
|
|
|
return (
|
|
<main>
|
|
<HeroSection />
|
|
<div className="divider" />
|
|
<DroneSection />
|
|
<div className="divider" />
|
|
<WebDevSection />
|
|
<div className="divider" />
|
|
<ProjectsSection />
|
|
<div className="divider" />
|
|
<TechMarquee />
|
|
<div className="divider" />
|
|
<ContactMeForm />
|
|
</main>
|
|
);
|
|
}
|