Skip to content

Commit

Permalink
[wip] create favorites list; adjust favorite button to include path a…
Browse files Browse the repository at this point in the history
…nd favorites list
  • Loading branch information
rebeccahongsf committed May 9, 2024
1 parent 16f8faf commit e4d3ccf
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const SummerCourse = ({hit}: Props) => {
</div>
}
<div className="ml-auto">
<FavoriteButton title={hit.title} uuid={hit.objectID} />
<FavoriteButton title={hit.title} uuid={hit.objectID} path={hit.url} units={hit.sum_course_units} />
</div>
</div>

Expand Down
37 changes: 37 additions & 0 deletions src/components/elements/favorite-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use client";
import useFavorites from "@lib/hooks/useFavorites";
import { HTMLAttributes } from "react";
import { HeartIcon } from "@heroicons/react/24/outline";
import { clsx } from "clsx";
import { useIsClient } from "usehooks-ts";

type Props = HTMLAttributes<HTMLButtonElement> & {
uuid: string;
title: string;
path: string;
units?: number;
};

const FavoriteButton = ({ uuid, title, path, units, ...props }: Props) => {
const { favs, addFav, removeFav } = useFavorites();
const isFavorite = favs.some((fav) => fav.uuid === uuid);

const onClick = () => {
isFavorite ? removeFav(uuid) : addFav(uuid, title, path, units);
};

// No need to add the button on the server, but also it doesn't show initial state correctly for some reason.
if (!useIsClient()) return null;

return (
<button onClick={onClick} role="switch" aria-checked={isFavorite} {...props}>
<HeartIcon
width={30}
className={clsx("text-spirited-dark", { "fill-spirited-dark": isFavorite })}
/>
<span className="sr-only">Add/Remove &quot;{title}&quot; from favorites</span>
</button>
);
};

export default FavoriteButton;
51 changes: 51 additions & 0 deletions src/components/elements/favorites-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";

import useFavorites from "@lib/hooks/useFavorites";
import {HeartIcon} from "@heroicons/react/24/outline";
import {useIsClient} from "usehooks-ts";
import { XMarkIcon } from "@heroicons/react/20/solid";


const FavoritesList = () => {
const { favs, removeFav } = useFavorites();

const removeFavorite = (uuid: string) => removeFav(uuid);

// No need to add the button on the server, but also it doesn't show initial state correctly for some reason.
if (!useIsClient()) return;

return (
<div>
{favs.length > 0 ?
<div>
Your favorites list is empty. Tap the{" "}
<HeartIcon width={30} className="text-spirited-dark" />{" "}
icon on courses you’re interested in to see them here. And share them with family and friends.
</div>
:
<>
<ul>
{favs.map(fav =>
<li key={fav.uuid}>
<button type="button" onClick={() => removeFavorite(fav.uuid)}>
<XMarkIcon width={24} />
<span className="sr-only">Remove &quot;{fav.title}&quot; from favorites</span>
</button>
<p>{fav.title}</p>
<p>Units {fav.units}</p>
</li>
)}
</ul>
<div>
Total units
</div>
</>
}
<div>
{/* Shareable options: Text, Email, Copy Link */}
</div>
</div>
);
};

export default FavoritesList
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HtmlHTMLAttributes} from "react";
import { HtmlHTMLAttributes } from "react";
import {getConfigPage} from "@lib/gql/gql-queries";
import {
StanfordBasicSiteSetting,
Expand All @@ -12,8 +12,8 @@ type Props = HtmlHTMLAttributes<HTMLDivElement> & {
}

const UserFavoriteParagraph = async ({ paragraph, ...props }: Props) => {
const { favs } = useFavorites();
const siteSettingsConfig = await getConfigPage<StanfordBasicSiteSetting>("StanfordBasicSiteSetting")
const { favs } = useFavorites();

if (!siteSettingsConfig?.suSiteAlgoliaId || !siteSettingsConfig.suSiteAlgoliaSearch || !siteSettingsConfig.suSiteAlgoliaIndex) {
return;
Expand All @@ -28,7 +28,8 @@ const UserFavoriteParagraph = async ({ paragraph, ...props }: Props) => {
appId={siteSettingsConfig.suSiteAlgoliaId}
searchIndex={siteSettingsConfig.suSiteAlgoliaIndex}
searchApiKey={siteSettingsConfig.suSiteAlgoliaSearch}
itemUuids={favs}
// itemUuids={favs}
itemUuids={[]}
// itemUuids={["eb0fe1c4-e98d-4fda-8962-4faa627340e0", "e66bd9be-a47b-4df7-804f-b173839e12aa", "e2979287-eef5-46a6-bb1e-e15e4c0e8280"]}
/>
</div>
Expand Down
24 changes: 15 additions & 9 deletions src/lib/hooks/useFavorites.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
"use client";

import { useCallback } from "react";
import { useLocalStorage, useIsClient } from "usehooks-ts";
import { useLocalStorage } from "usehooks-ts";

type Favorite = {
uuid: string;
title: string;
path: string;
units: number;
};

const useFavorites = (): {
favs: string[];
addFav: (_uuid: string) => void;
favs: Favorite[];
addFav: (_uuid: string, _title: string, _path: string, _units?: number) => void;
removeFav: (_uuid: string) => void;
} => {
const isClient = useIsClient();
const [favs, setFavs] = useLocalStorage<string[]>("favorites", [], { initializeWithValue: false });
const [favs, setFavs] = useLocalStorage<Favorite[]>("favorites", [], {initializeWithValue: false});

const addFav = useCallback(
(uuid: string) => {
setFavs([...favs, uuid ]);
(uuid: string, title: string, path: string, units: number) => {
setFavs([...favs, { uuid, title, path, units }]);
},
[favs, setFavs]
);

const removeFav = useCallback(
(uuid: string) => {
const updatedFavs = favs.filter((fav) => fav !== uuid);
const updatedFavs = favs.filter((fav) => fav.uuid !== uuid);
setFavs(updatedFavs);
},
[favs, setFavs]
);

return { favs: isClient ? favs : [], addFav, removeFav };
return { favs, addFav, removeFav };
};

export default useFavorites;

0 comments on commit e4d3ccf

Please sign in to comment.