Skip to content

Commit

Permalink
Merge pull request #48 from cs3216-a3-group-4/haoyang/integrate-part2
Browse files Browse the repository at this point in the history
Improve home page top events UI
  • Loading branch information
haoyangw authored Sep 25, 2024
2 parents 0d91d68 + 24e5683 commit bb920b1
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 29 deletions.
35 changes: 27 additions & 8 deletions frontend/app/home.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useEffect, useState } from "react";

import { getEventsEventsGet, MiniEventDTO } from "@/client";
import ArticleLoading from "@/components/news/article-loading";
import NewsArticle from "@/components/news/news-article";
import { useUserStore } from "@/store/user/user-store-provider";

const NUM_TOP_EVENTS = 10;
const DAYS_PER_WEEK = 7;
Expand All @@ -10,6 +12,7 @@ const DAYS_PER_WEEK = 7;
const Home = () => {
const [topEvents, setTopEvents] = useState<MiniEventDTO[]>([]);
const [isLoaded, setIsLoaded] = useState<boolean>(false);
const user = useUserStore((state) => state.user);

useEffect(() => {
const fetchTopEvents = async () => {
Expand All @@ -20,12 +23,24 @@ const Home = () => {
.toISOString()
.split("T")[0];

const response = await getEventsEventsGet({
query: {
start_date: formattedEventStartDate,
limit: NUM_TOP_EVENTS,
},
});
let eventQuery;
if (user?.categories && user.categories.length > 0) {
eventQuery = {
query: {
start_date: formattedEventStartDate,
limit: NUM_TOP_EVENTS,
category_ids: user.categories.map((category) => category.id),
},
};
} else {
eventQuery = {
query: {
start_date: formattedEventStartDate,
limit: NUM_TOP_EVENTS,
},
};
}
const response = await getEventsEventsGet(eventQuery);

if (response.error) {
console.log(response.error);
Expand All @@ -36,7 +51,7 @@ const Home = () => {
};

fetchTopEvents();
}, []);
}, [user]);

return (
<div className="flex flex-col w-full py-8">
Expand All @@ -51,7 +66,11 @@ const Home = () => {

<div className="flex flex-col w-auto mx-4 md:mx-8 xl:mx-24">
{!isLoaded ? (
<p>Loading data...</p>
<>
<ArticleLoading />
<ArticleLoading />
<ArticleLoading />
</>
) : (
topEvents.map((newsEvent: MiniEventDTO, index: number) => (
<NewsArticle key={index} newsEvent={newsEvent} />
Expand Down
27 changes: 27 additions & 0 deletions frontend/components/icons/placeholder-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const PlaceholderImage = ({ classname }: { classname?: string }) => {
return (
<div className="flex flex-wrap place-content-center bg-gray-100 w-full h-full p-1">
<div className="flex h-1/2">
<svg
className={`${classname} h-full w-full`}
fill="none"
viewBox="0 0 132 132"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M40.9999 89.2632C37.4999 83 44.5177 73.9921 52.4998 72C62.5172 69.5 76.2429 75.8588 80.7928 89.2632C85.5774 103.359 78.7019 118.625 64.7614 123.846C51 129 40 127 28.5002 121C10.4065 111.56 2.49991 89.2632 6.76136 65.8462C16.0139 15.0025 112.563 -19.2824 122.761 27.3462C126.936 46.4359 109.5 58.5 100.793 77.2632C97.0116 85.4107 96.7925 93.0265 98.7925 99.7632C100.793 106.5 106.481 115.119 117 118.5"
stroke="#D1D5DB"
strokeLinecap="round"
strokeWidth="7"
/>
<path
d="M90.5395 31.7036C88.9019 35.0846 89.6241 38.4518 92.2096 41.1771C95.6087 44.76 101.735 45.0045 104.856 41.1771C107.401 38.056 107.271 34.0871 104.856 30.8643C101.497 26.3827 92.9808 26.6632 90.5395 31.7036Z"
fill="#D1D5DB"
/>
</svg>
</div>
</div>
);
};

export default PlaceholderImage;
26 changes: 26 additions & 0 deletions frontend/components/news/article-loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const ArticleLoading = () => {
return (
<div className="flex flex-col-reverse animate-pulse py-10 lg:py-6 xl:py-4 gap-x-16 border-y-[1px] lg:border-y-[0px] hover:bg-muted/70 lg:rounded-md px-4 md:px-8">
<div className="flex flex-col w-full lg:w-7/12 2xl:w-9/12 3xl:w-10/12">
<div className="flex flex-row justify-between w-full">
{/* Article source placeholder */}
<div className="h-3 bg-gray-300 rounded w-1/6 mb-2"></div>
{/* Article date placeholder */}
<div className="h-3 bg-gray-300 rounded w-1/4 mb-2"></div>
</div>
{/* Event title placeholder */}
<div className="h-4 bg-gray-300 rounded w-2/3 mb-2 mt-2"></div>
{/* Event description placeholder */}
<div className="h-6 bg-gray-300 rounded w-5/6 mb-4"></div>
{/* Event category placeholder */}
<div className="flex flex-wrap gap-x-2 gap-y-2 mt-6">
<div className="rounded h-5 bg-gray-300 w-14 mb-2"></div>
</div>
</div>
{/* Event image placeholder */}
<div className="min-h-32 bg-gray-300 rounded w-full lg:w-5/12 2xl:w-3/12 3xl:w-2/12 mb-6"></div>
</div>
);
};

export default ArticleLoading;
51 changes: 31 additions & 20 deletions frontend/components/news/news-article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ArrowUpRightIcon } from "lucide-react";

import { CategoryDTO, MiniEventDTO } from "@/client";
import Chip from "@/components/display/chip";
import PlaceholderImage from "@/components/icons/placeholder-image";
import {
categoriesToDisplayName,
categoriesToIconsMap,
Expand All @@ -15,15 +16,19 @@ const NewsArticle = (props: { newsEvent: MiniEventDTO }) => {
const newsEvent = props.newsEvent;
const newsArticle = newsEvent.original_article;
const [categories, setCategories] = useState<Category[]>([]);
const PLACEHOLDER_IMG_URL =
"https://upload.wikimedia.org/wikipedia/commons/3/3f/Placeholder_view_vector.svg";
const IMG_HEIGHT = 154;

useEffect(() => {
setCategories(
newsEvent.categories.map((category: CategoryDTO) =>
getCategoryFor(category.name),
),
);
try {
setCategories(
newsEvent.categories.map((category: CategoryDTO) =>
getCategoryFor(category.name),
),
);
} catch (error) {
console.log(error);
setCategories([Category.Others]);
}
}, [newsEvent]);

const parseDate = (dateString: string) => {
Expand Down Expand Up @@ -51,28 +56,34 @@ const NewsArticle = (props: { newsEvent: MiniEventDTO }) => {
<h2 className="text-lg font-semibold mt-2">{newsEvent.title}</h2>
<p className="text-sm text-offblack">{newsEvent.description}</p>
<div className="flex flex-wrap gap-x-2 gap-y-2 mt-6">
{categories?.map((category: Category) => (
{categories?.map((category: Category, index: number) => (
<Chip
Icon={categoriesToIconsMap[category]}
key={category}
key={index}
label={categoriesToDisplayName[category]}
variant="greygreen"
/>
))}
</div>
</div>
<div className="flex w-full lg:w-5/12 2xl:w-3/12 3xl:w-2/12 mb-6 items-center">
<Image
alt=""
height={154}
src={newsArticle.image_url || PLACEHOLDER_IMG_URL}
style={{
width: "100%",
height: "fit-content",
}}
unoptimized
width={273}
/>
{newsArticle.image_url ? (
<Image
alt=""
height={IMG_HEIGHT}
src={newsArticle.image_url}
style={{
width: "100%",
height: "fit-content",
}}
unoptimized
width={273}
/>
) : (
<div className="flex w-full" style={{ height: `${IMG_HEIGHT}px` }}>
<PlaceholderImage />
</div>
)}
</div>
</div>
);
Expand Down
9 changes: 8 additions & 1 deletion frontend/types/categories.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Building2,
CircleHelp,
DollarSign,
Film,
HeartHandshake,
Expand All @@ -23,6 +24,7 @@ export enum Category {
GenderEquality = "Gender & equality",
Religion = "Religion",
SocietyCulture = "Society & culture",
Others = "Others",
}

export const getCategoryFor = (categoryName: string) => {
Expand All @@ -39,7 +41,10 @@ export const getCategoryFor = (categoryName: string) => {
"society & culture": Category.SocietyCulture,
};
const formattedName = categoryName.toLowerCase();
return mappings[formattedName];
if (formattedName in mappings) {
return mappings[formattedName];
}
return Category.Others;
};

export const categoriesToDisplayName: Record<Category, string> = {
Expand All @@ -53,6 +58,7 @@ export const categoriesToDisplayName: Record<Category, string> = {
[Category.GenderEquality]: "Gender & equality",
[Category.Religion]: "Religion",
[Category.SocietyCulture]: "Society & culture",
[Category.Others]: "Others",
};

export const categoriesToIconsMap: Record<Category, LucideIcon> = {
Expand All @@ -66,4 +72,5 @@ export const categoriesToIconsMap: Record<Category, LucideIcon> = {
[Category.GenderEquality]: Scale,
[Category.Religion]: HeartHandshake,
[Category.SocietyCulture]: UsersRound,
[Category.Others]: CircleHelp,
};

0 comments on commit bb920b1

Please sign in to comment.