Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review Implementation #151

Merged
merged 11 commits into from
Sep 24, 2024
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@lexical/react": "^0.12.2",
"@nanostores/persistent": "^0.9.1",
"@nanostores/solid": "^0.4.2",
"@neodrag/solid": "^2.0.4",
"@playwright/test": "^1.41.2",
"@stripe/stripe-js": "^3.0.6",
"@supabase/supabase-js": "^2.39.6",
Expand Down
2 changes: 2 additions & 0 deletions src/components/common/notices/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type ModalProps = {
buttonContent: JSX.Element;
heading: HeadingProps["heading"];
headingLevel?: HeadingProps["headingLevel"];
classList?: string;
};

const Modal: Component<ModalProps> = (props) => {
Expand Down Expand Up @@ -70,6 +71,7 @@ const Modal: Component<ModalProps> = (props) => {
e.stopPropagation();
setIsOpen(false);
}

return (
<>
<button
Expand Down
28 changes: 6 additions & 22 deletions src/components/home/HomeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslations } from "../../i18n/utils";
import { lazyLoadImage } from "@lib/imageHelper";
import postPlaceHolder from "@src/assets/postPlaceHolder.svg";
import person from "@src/assets/person.svg";
import { AverageRatingStars } from "@components/posts/AverageRatingStars";

interface Props {
// Define the type for the filterPosts prop
Expand Down Expand Up @@ -164,28 +165,11 @@ export const HomeCard: Component<Props> = (props) => {
id="homeCard-ratings-price"
class="row-span-1 text-end"
>
{/* <div class="flex w-2/3 items-end"> */}
{/* <div class="flex items-end justify-start"> */}
{/* <svg */}
{/* xmlns="http://www.w3.org/2000/svg" */}
{/* width="15px" */}
{/* height="15px" */}
{/* viewBox="0 0 32 32" */}
{/* class="fill-icon1 dark:fill-icon1-DM" */}
{/* > */}
{/* <path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" /> */}
{/* </svg> */}
{/**/}
{/* <p class="ml-1 mr-0.5 text-xs font-bold"> */}
{/* 4.9 */}
{/* </p> */}
{/* <p class="text-xs font-light"> */}
{/* (30.3K) */}
{/* </p> */}
{/* </div> */}
{/* </div> */}

<div class=" text-end">
<div class="my-1 flex justify-between text-end">
<AverageRatingStars
resourceId={post.id}
page={"home"}
/>
<Show when={post.price > 0}>
<p class="text-xs font-bold">
${post.price.toFixed(2)}
Expand Down
5 changes: 4 additions & 1 deletion src/components/members/UserProfileView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ export const UserProfileView: Component = () => {
<Show when={screenSize() === "sm"}>
<UserProfileViewMobile
user={user() ? user()! : null}
session={session()}
editMode={editMode()}
enableEditMode={enableEditMode}
userImage={userImage()}
Expand Down Expand Up @@ -487,7 +488,9 @@ export const UserProfileView: Component = () => {
{/* <Show when={ purchasedItems() }> */}
<div>
{/* <ViewCard posts={purchasedItems()} /> */}
<ViewUserPurchases />
<ViewUserPurchases
session={session()}
/>
</div>
{/* </Show>

Expand Down
4 changes: 3 additions & 1 deletion src/components/members/UserProfileViewMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import type { User } from "@lib/types";
import type { Post } from "@lib/types";
import { ViewUserPurchases } from "@components/posts/ViewUserPurchases";
import { ViewUserFavorites } from "@components/posts/ViewUserFavorites";
import type { AuthSession } from "@supabase/supabase-js";

const lang = getLangFromUrl(new URL(window.location.href));
const t = useTranslations(lang);

interface Props {
user: User | null;
session: AuthSession | null;
userImage: string | undefined;
editMode: boolean;
enableEditMode: () => void;
Expand Down Expand Up @@ -357,7 +359,7 @@ export const UserProfileViewMobile: Component<Props> = (props: Props) => {

<Show when={tabSelected() === "purchases"}>
<div>
<ViewUserPurchases />
<ViewUserPurchases session={props.session} />
</div>
</Show>

Expand Down
253 changes: 253 additions & 0 deletions src/components/posts/AverageRatingStars.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import { getLangFromUrl, useTranslations } from "@i18n/utils";
import {
createEffect,
createResource,
createSignal,
onMount,
Suspense,
Show,
type Component,
} from "solid-js";
import type { Review } from "@lib/types";

interface Props {
resourceId: number;
page: string;
}

async function fetchPostRatings(resourceId: string) {
const response = await fetch("/api/getRatings", {
method: "POST",
body: JSON.stringify({ resource_id: resourceId }),
});
const data = await response.json();
if (data.redirect) {
window.location.href = data.redirect;
}
if (response.status === 200) {
console.log(data);
}
return data;
}

export const AverageRatingStars: Component<Props> = (props) => {
const [ratingsData, setRatingsData] = createSignal([]);
const [showEmptyStars, setShowEmptyStars] = createSignal(false);
const [totalRatings, setTotalRatings] = createSignal(0);
const [ratingsSum, setRatingsSum] = createSignal(0);
const [averageRating, setAverageRating] = createSignal(0);

const lang = getLangFromUrl(new URL(window.location.href));
const t = useTranslations(lang);

onMount(async () => {
try {
const data = await fetchPostRatings(props.resourceId.toString());
setRatingsData(data.body);
} catch (err) {
console.error(err);
} finally {
const arrayLength = () => ratingsData().length;
if (arrayLength() === 0) {
setShowEmptyStars(true);
return;
}
setTotalRatings(arrayLength);

if (arrayLength() > 0) {
ratingsData().map((rating: Review) => {
setRatingsSum(rating.overall_rating + ratingsSum());
});
}
setAverageRating(ratingsSum() / totalRatings());
setAverageRating(Math.round(averageRating() * 2) / 2);
}
});

return (
<div>
<Show when={props.page === "home" || props.page === "mobileFullDetails" || props.page === "viewCard"}>
<div class="flex items-center justify-start">
<svg
id="star1"
fill="none"
width="16px"
height="16px"
viewBox="0 0 32 32"
class="mr-0.5 fill-icon1 stroke-icon1 stroke-1 dark:fill-icon2 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
<p class="mr-1 text-xs font-bold">{averageRating()}</p>
<p class="text-xs font-light">({totalRatings()})</p>
</div>
</Show>
<Show when={props.page === "fullCard"}>
<div class="flex items-center justify-center">
<Show
when={
(averageRating() >= 1 && averageRating() < 2) ||
(averageRating() >= 2 && averageRating() < 3) ||
(averageRating() >= 3 && averageRating() < 4) ||
(averageRating() >= 4 && averageRating() < 5) ||
averageRating() === 5
}
fallback={
<div>
<svg
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="emptyStar fill-none stroke-icon1 stroke-1 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</div>
}
>
<svg
id="star1"
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="fill-icon1 stroke-icon1 stroke-1 dark:fill-icon2 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</Show>

<Show
when={
(averageRating() >= 1 && averageRating() < 2) ||
(averageRating() >= 2 && averageRating() < 3) ||
(averageRating() >= 3 && averageRating() < 4) ||
(averageRating() >= 4 && averageRating() < 5) ||
averageRating() === 5
}
fallback={
<div>
<svg
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="emptyStar fill-none stroke-icon1 stroke-1 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</div>
}
>
<svg
id="star2"
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="fill-icon1 stroke-icon1 stroke-1 dark:fill-icon2 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</Show>

<Show
when={
(averageRating() >= 3 && averageRating() < 4) ||
(averageRating() >= 4 && averageRating() < 5) ||
averageRating() === 5
}
fallback={
<div>
<svg
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="emptyStar fill-none stroke-icon1 stroke-1 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</div>
}
>
<svg
id="star3"
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="fill-icon1 stroke-icon1 stroke-1 dark:fill-icon2 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</Show>

<Show
when={
(averageRating() >= 4 && averageRating() < 5) ||
averageRating() === 5
}
fallback={
<div>
<svg
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="emptyStar fill-none stroke-icon1 stroke-1 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</div>
}
>
<svg
id="star4"
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="fill-icon1 stroke-icon1 stroke-1 dark:fill-icon2 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</Show>

<Show
when={averageRating() === 5}
fallback={
<div>
<svg
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="emptyStar fill-none stroke-icon1 stroke-1 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</div>
}
>
<svg
id="star5"
fill="none"
width="20px"
height="20px"
viewBox="0 0 32 32"
class="fill-icon1 stroke-icon1 stroke-1 dark:fill-icon2 dark:stroke-icon2"
>
<path d="M 30.335938 12.546875 L 20.164063 11.472656 L 16 2.132813 L 11.835938 11.472656 L 1.664063 12.546875 L 9.261719 19.394531 L 7.140625 29.398438 L 16 24.289063 L 24.859375 29.398438 L 22.738281 19.394531 Z" />
</svg>
</Show>
<div class="flex ml-1">
<p class="mr-1 text-xs md:text-lg font-bold">{averageRating()}</p>
<p class="text-xs md:text-lg font-light">({totalRatings()}) {t("postLabels.reviews")}</p>
</div>
</div>
</Show>
</div>
);
};
Loading
Loading