feat: Added popular topics pill-link section to homepage that fetches f…
- "frontend/src/pages/Home.tsx" - "frontend/src/App.css" GSD-Task: S01/T02
This commit is contained in:
parent
881629b5c3
commit
5f7a8a6f77
2 changed files with 83 additions and 0 deletions
|
|
@ -953,6 +953,50 @@ a.app-footer__repo:hover {
|
|||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* ── Popular topics quick-links ───────────────────────────────────────────── */
|
||||
|
||||
.home-popular-topics {
|
||||
margin-top: 2.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.home-popular-topics__title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.home-popular-topics__list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
max-width: 36rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.pill--topic-quick {
|
||||
display: inline-block;
|
||||
padding: 0.375rem 0.875rem;
|
||||
border-radius: 9999px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
background: var(--color-pill-bg);
|
||||
color: var(--color-pill-text);
|
||||
border: 1px solid var(--color-border);
|
||||
text-decoration: none;
|
||||
transition: border-color 0.15s, background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.pill--topic-quick:hover {
|
||||
border-color: var(--color-accent);
|
||||
background: var(--color-accent-subtle);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
/* ── Search form ──────────────────────────────────────────────────────────── */
|
||||
|
||||
.search-container {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { Link, useNavigate } from "react-router-dom";
|
|||
import {
|
||||
searchApi,
|
||||
fetchTechniques,
|
||||
fetchTopics,
|
||||
type SearchResultItem,
|
||||
type TechniqueListItem,
|
||||
} from "../api/public-client";
|
||||
|
|
@ -21,6 +22,7 @@ export default function Home() {
|
|||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
const [recent, setRecent] = useState<TechniqueListItem[]>([]);
|
||||
const [recentLoading, setRecentLoading] = useState(true);
|
||||
const [popularTopics, setPopularTopics] = useState<{name: string; count: number}[]>([]);
|
||||
const navigate = useNavigate();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
|
@ -49,6 +51,26 @@ export default function Home() {
|
|||
};
|
||||
}, []);
|
||||
|
||||
// Load popular topics
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
void (async () => {
|
||||
try {
|
||||
const categories = await fetchTopics();
|
||||
const all = categories.flatMap((cat) =>
|
||||
cat.sub_topics.map((st) => ({ name: st.name, count: st.technique_count }))
|
||||
);
|
||||
all.sort((a, b) => b.count - a.count);
|
||||
if (!cancelled) setPopularTopics(all.slice(0, 8));
|
||||
} catch {
|
||||
// optional section — silently ignore
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Close dropdown on outside click
|
||||
useEffect(() => {
|
||||
function handleClick(e: MouseEvent) {
|
||||
|
|
@ -198,6 +220,23 @@ export default function Home() {
|
|||
</div>
|
||||
|
||||
<Link to="/topics" className="btn home-cta">Start Exploring</Link>
|
||||
|
||||
{popularTopics.length > 0 && (
|
||||
<section className="home-popular-topics">
|
||||
<h2 className="home-popular-topics__title">Popular Topics</h2>
|
||||
<div className="home-popular-topics__list">
|
||||
{popularTopics.map((topic) => (
|
||||
<Link
|
||||
key={topic.name}
|
||||
to={`/search?q=${encodeURIComponent(topic.name)}&scope=topics`}
|
||||
className="pill pill--topic-quick"
|
||||
>
|
||||
{topic.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* Navigation cards */}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue