Skip to content

Commit

Permalink
add glossary and tag type pages
Browse files Browse the repository at this point in the history
  • Loading branch information
asligook committed Dec 16, 2024
1 parent d94be23 commit 4cae533
Show file tree
Hide file tree
Showing 8 changed files with 365 additions and 22 deletions.
1 change: 1 addition & 0 deletions frontend/src/components/NavbarLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { Sheet, SheetContent, SheetTrigger } from "./ui/sheet";

const links = [
{ name: "Home", path: "/" },
{ name: "Glossary", path: "/glossary" }, //add glossary page to the navbar
{ name: "Tags", path: "/tags" },
] as const;

Expand Down
51 changes: 51 additions & 0 deletions frontend/src/components/SubtypeCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Card } from "@/components/ui/card";
import { ArrowRight, Tags } from "lucide-react";
import React from "react";
import { Link } from "react-router-dom";

interface TagSubtypeCardProps {
tagSubtype: {
typeId: string;
tagCount: number;
description: string; // Added description field
};
}

export const TagSubtypeCard = React.forwardRef<
HTMLDivElement,
TagSubtypeCardProps
>(({ tagSubtype }, ref) => {
return (
<Card
className="flex-1 border-none bg-neutral-100 px-6 py-8 shadow-sm"
ref={ref}
>
<div className="flex flex-col gap-6">
{/* Subtype Name */}
<h1 className="text-xl font-semibold text-gray-800">
{tagSubtype.typeId}
</h1>

{/* Description */}
<p className="text-sm text-gray-600">{tagSubtype.description}</p>

{/* Number of Tags */}
<div className="flex items-center gap-2 text-sm text-gray-700">
<Tags className="h-5 w-5" />
<span>{tagSubtype.tagCount} tags</span>
</div>

{/* Navigation Link */}
<div className="flex justify-end">
<Link
to={`/tagtype/${tagSubtype.typeId}`}
className="flex items-center text-sm font-medium text-gray-800 hover:underline"
>
View tag type page
<ArrowRight className="ml-1 h-4 w-4" />
</Link>
</div>
</div>
</Card>
);
});
17 changes: 11 additions & 6 deletions frontend/src/components/TagCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,17 @@ export const TagCard = React.forwardRef<HTMLDivElement, TagCardProps>(
<Hash className="h-4 w-4" />
<span>{tag.questionCount} questions</span>
</div>
{tag.tagType && (
<div className="flex items-center gap-1">
<Tag className="h-4 w-4" />
<span>{tag.tagType}</span>
</div>
)}
<Link
to={`/tagtype/${tag.tagType}`}
className="flex items-center text-sm font-medium text-gray-800 hover:underline"
>
{tag.tagType && (
<div className="flex items-center gap-1">
<Tag className="h-4 w-4" />
<span>{tag.tagType}</span>
</div>
)}
</Link>
</div>
<div className="flex items-center justify-between">
{tag.logoImage && (
Expand Down
181 changes: 181 additions & 0 deletions frontend/src/components/TagType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { Loader2 } from "lucide-react";
import { TagCard } from "@/components/TagCard";
import { useSearchTags } from "@/services/api/programmingForumComponents";
import { TagDetails } from "@/services/api/programmingForumSchemas";
import ErrorAlert from "@/components/ErrorAlert";
import InfiniteScroll from "@/components/InfiniteScroll";

export default function SubtypePage() {
const { typeId } = useParams<{ typeId: string }>();
const [tags, setTags] = useState<TagDetails[]>([]);
const [tagTypeId, setTagTypeId] = useState<string | undefined>();

const [pageSize, setPageSize] = useState(20);
const [previousData, setPreviousData] = useState<{
items: TagDetails[];
totalItems: number;
}>({ items: [], totalItems: 0 });

const {
data: tagSearchData,
isLoading,
error,
} = useSearchTags(
{
queryParams: { q: "", pageSize },
},
{ enabled: true },
);

useEffect(() => {
if (tagSearchData?.data) {
const availableTags = (tagSearchData.data as { items: TagDetails[] })
.items;

// Filter tags by the typeId
const filteredTags = availableTags.filter(
(tag) => tag.tagType === typeId,
);

setTags(filteredTags);

// Set the tag type name and description
if (filteredTags.length > 0) {
setTagTypeId(typeId);
//setTagDescription(`Description for ${typeId} tags.`); // Replace with actual description if available
} else {
setTagTypeId("Unknown Tag Type");
//setTagDescription("No description available for this tag type.");
}
}
}, [tagSearchData, typeId]);

useEffect(() => {
if (tagSearchData?.data && !isLoading) {
setPreviousData(tagSearchData.data as typeof previousData);
}
}, [tagSearchData, isLoading]);

const searchResultData =
(tagSearchData?.data as {
items?: TagDetails[];
totalItems?: number;
}) || previousData;

const next = () => {
setPageSize(pageSize + 20);
};

//descriptions for the tag types
const getDescription = (TypeId: string) => {
switch (TypeId) {
case "Programming Language":
return (
<p>
A programming language is a formal system used to communicate
instructions to a machine, particularly a computer. It consists of
syntax, semantics, and rules that allow developers to write software
and algorithms. Programming languages enable the creation of
programs that can execute tasks ranging from simple calculations to
complex data processing and system management. Well-known examples
include Python, Java, and C++.
</p>
);
case "Programming Paradigm":
return (
<p>
A programming paradigm refers to a fundamental style or approach to
programming that influences how software is structured and
developed. It encompasses the methodologies and principles that
guide the design and implementation of programs, including
object-oriented programming, functional programming, and procedural
programming. Different paradigms offer distinct ways of thinking
about and solving problems in software development.
</p>
);
case "Computer Science Term":
return (
<p>
A computer science term is a word or phrase that is part of the
technical vocabulary of computer science. These terms represent
concepts, theories, tools, or techniques that are essential to
understanding the field. Examples include terms like algorithm, data
structure, machine learning, and artificial intelligence. These
terms form the foundation of communication and learning within the
computer science discipline.
</p>
);
case "Software Library":
return (
<p>
A software library is a collection of pre-written code, functions,
and resources that developers can use to perform common tasks
without having to write code from scratch. Libraries are designed to
provide reusable components for tasks such as data manipulation,
user interface design, and network communication. Popular software
libraries include jQuery for web development, TensorFlow for machine
learning, and NumPy for numerical computations.
</p>
);
}
};

const description = typeId ? (
getDescription(typeId)
) : (
<p>Loading description...</p>
);

if (error) {
return <ErrorAlert error={error} />;
}

return (
<div className="container py-8">
{isLoading ? (
<div className="flex items-center justify-center">
<Loader2
aria-label="Loading"
className="h-16 w-16 animate-spin text-primary"
/>
</div>
) : (
<>
{/* Header */}
<h1 className="mb-4 text-4xl font-bold text-gray-800">{tagTypeId}</h1>

{/* Render the description based on typeId */}
<div className="mb-6 text-lg text-gray-700">{description}</div>

{/* Tags in this Category Section */}
<h2 className="mb-4 text-2xl font-semibold text-gray-800">
Tags in This Category:
</h2>

{/* Infinite Scroll for displaying Related Tags */}
<div className="grid grid-cols-3 gap-4">
<InfiniteScroll
next={next}
hasMore={
searchResultData.totalItems
? searchResultData.totalItems > pageSize
: false
}
isLoading={isLoading}
>
{tags.length > 0 ? (
tags.map((tag) => <TagCard key={tag.tagId} tag={tag} />)
) : (
<p className="col-span-3 text-center text-gray-600">
No related tags found for this tag type.
</p>
)}
</InfiniteScroll>
</div>
</>
)}
</div>
);
}
89 changes: 89 additions & 0 deletions frontend/src/routes/glossary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { TagSubtypeCard } from "@/components/SubtypeCard";
import { useSearchTags } from "@/services/api/programmingForumComponents";
import { TagDetails } from "@/services/api/programmingForumSchemas";
import { Loader2 } from "lucide-react";
import { useEffect, useState } from "react";
import ErrorAlert from "@/components/ErrorAlert";

export default function GlossaryPage() {
const [tagCounts, setTagCounts] = useState<
{ typeId: string; tagCount: number; description: string }[] // Added description field
>([]);
const [, setAvailableTags] = useState<TagDetails[]>([]);

const {
data: tagSearchData,
isLoading,
error,
} = useSearchTags(
{ queryParams: { q: "", pageSize: 400 } },
{ enabled: true },
);

useEffect(() => {
if (tagSearchData?.data) {
// Extract available tags
const tags = (tagSearchData.data as { items: TagDetails[] }).items;
setAvailableTags(tags);

// Define the 4 tag types with descriptions from wikidata
const tagTypes = [
{
typeId: "Programming Language",
description: "language for communicating instructions to a machine",
},
{
typeId: "Software Library",
description:
"collection of non-volatile resources used by computer programs, often for software development",
},
{
typeId: "Programming Paradigm",
description:
"category of programming languages according to what methodology of designing and implementing programs their features support",
},
{
typeId: "Computer Science Topic",
description:
"technical term; word or phrase that is part of computer science terminology",
},
];

// group and count tags by tagType
const counts = tagTypes.map((type) => {
const filteredTags = tags.filter((tag) => tag.tagType === type.typeId);
return {
typeId: type.typeId,
tagCount: filteredTags.length,
description: type.description,
};
});

setTagCounts(counts);
}
}, [tagSearchData]);

if (error) {
return <ErrorAlert error={error} />;
}

return (
<div className="container py-8">
<h1 className="mb-4 text-4xl font-bold">Explore Various Tag Types</h1>
<div className="grid grid-cols-4 gap-4 py-4">
{tagCounts.map((tagCount) => (
<TagSubtypeCard key={tagCount.typeId} tagSubtype={tagCount} />
))}

{isLoading && (
<div className="col-span-3 flex w-full items-center justify-center">
<Loader2
aria-label="Loading"
className="h-16 w-16 animate-spin text-primary"
/>
</div>
)}
</div>
</div>
);
}
10 changes: 10 additions & 0 deletions frontend/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { Search } from "./search";
import Signup from "./signup";
import TagPage from "./tag";
import { BookmarkedQuestions } from "@/routes/bookmarks";
import Glossary from "./glossary";
import TagTypePage from "@/components/TagType";

export const routes: RouteObject[] = [
{
Expand Down Expand Up @@ -66,6 +68,14 @@ export const routes: RouteObject[] = [
path: "/tags/new",
Component: CreateTagPage,
},
{
path: "/glossary",
Component: Glossary,
},
{
path: "/tagtype/:typeId",
Component: TagTypePage,
},
];

export const routeConfig: RouteObject[] = [
Expand Down
Loading

0 comments on commit 4cae533

Please sign in to comment.