Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/Weaverse/pilot into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
hta218 committed Oct 16, 2024
2 parents 8570a01 + a337571 commit 5fadc73
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 198 deletions.
1 change: 1 addition & 0 deletions app/lib/judgeme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type JudgemeProductData = {
type JudgemeReviewType = {
id: string;
title: string;
created_at: string;
body: string;
rating: number;
reviewer: {
Expand Down
32 changes: 16 additions & 16 deletions app/sections/judgeme-reviews/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ import type {
HydrogenComponentSchema
} from "@weaverse/hydrogen";
import { forwardRef } from "react";
import { backgroundInputs } from "~/components/background-image";
import { Section, layoutInputs } from "~/components/section";

let JudgemeReviewSection = forwardRef<HTMLElement, any>((props, ref) => {
let { children, loaderData, ...rest } = props;
return (
<Section ref={ref} {...rest} overflow="unset">
<div className="max-w-4xl mx-auto py-6 px-8 bg-white rounded shadow">
{children}
</div>
</Section>
);
});
Expand All @@ -22,21 +19,24 @@ export let schema: HydrogenComponentSchema = {
type: "judgeme-reviews",
title: "Judgeme Reviews",
inspector: [
// {
// group: "Layout",
// inputs: layoutInputs.filter((inp) => inp.name !== "borderRadius"),
// },
// {
// group: "Background",
// inputs: backgroundInputs.filter((inp) => inp.name === "backgroundColor"),
// },
{
group: "Layout",
inputs: layoutInputs.filter((inp) => inp.name !== "borderRadius"),
},
],
childTypes: [
"heading",
"subheading",
"paragraph",
"button",
"judgeme-review--form",
"judgeme-review--list",
"judgeme-review--index",
],
presets: {
children: [
{
type: "heading",
Content: "Reviews",
},
{
type: "judgeme-review--index",
},
],
},
};
276 changes: 157 additions & 119 deletions app/sections/judgeme-reviews/review-form.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { useFetcher, useLoaderData } from "@remix-run/react";
import { HydrogenComponentSchema } from "@weaverse/hydrogen";
import { FormEvent, forwardRef, useEffect, useRef, useState } from "react";
import { FormEvent, useEffect, useRef, useState } from "react";
import Button from "~/components/button";
import { IconStar, IconStarFilled } from "~/components/icons";
import { StarRating } from "~/modules/star-rating";
import { ProductLoaderType } from "~/routes/($locale).products.$productHandle";

type ReviewFormProps = {};

let ReviewForm = forwardRef<HTMLDivElement, ReviewFormProps>((props, ref) => {
const { product } = useLoaderData<ProductLoaderType>();
let { ...rest } = props;
export function ReviewForm() {
const { product, judgemeReviews } = useLoaderData<ProductLoaderType>();
const [rating, setRating] = useState(0);
const [hover, setHover] = useState(0);
const [submitSuccess, setSubmitSuccess] = useState(false);
const [isFormVisible, setIsFormVisible] = useState(false);
const [isPopupVisible, setIsPopupVisible] = useState(false);
const fetcher = useFetcher<any>();
const formRef = useRef<HTMLFormElement>(null);
let [message, setMessage] = useState("");
Expand All @@ -23,12 +21,11 @@ let ReviewForm = forwardRef<HTMLDivElement, ReviewFormProps>((props, ref) => {
if (fetcher.data) {
setMessage((fetcher.data as any)?.message || "");
if (fetcher.data.success) {
setSubmitSuccess(true);
setIsFormVisible(false);
setIsPopupVisible(true);
setRating(0);
setHover(0);
(formRef as React.MutableRefObject<HTMLFormElement>).current?.reset();
} else {
setSubmitSuccess(false);
}
}
}, [fetcher.data]);
Expand All @@ -42,123 +39,164 @@ let ReviewForm = forwardRef<HTMLDivElement, ReviewFormProps>((props, ref) => {
};

return (
<div ref={ref} {...rest}>
<div className="flex flex-col sm:flex-row items-center my-6 gap-2">
<div className="flex items-center">
{[...Array(5)].map((_, index) => {
const ratingValue = index + 1;
return (
<div
key={index}
onClick={() => handleRatingClick(ratingValue)}
onMouseEnter={() => setHover(ratingValue)}
onMouseLeave={() => setHover(0)}
aria-label={`Rate ${ratingValue} out of 5 stars`}
role="button"
>
{ratingValue <= (hover || rating) ? (
<IconStarFilled />
) : (
<IconStar />
)}
</div>
);
})}
</div>
<span className="text-gray-600">{rating} out of 5</span>
</div>
{/* Review Form */}
<fetcher.Form
onSubmit={handleSubmit}
className="mb-8"
ref={formRef}
method="POST"
encType="multipart/form-data"
>
<input type="hidden" name="rating" value={rating} />
<input type="hidden" name="id" value={internalId} />
<div className="mb-4">
<label htmlFor="name" className="block text-gray-700 font-bold mb-2">
Your name
</label>
<input
required
type="text"
id="name"
name="name"
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
/>
<div className="lg:w-1/3 md:w-2/5 w-full flex flex-col gap-5">
<div className="flex flex-col items-start gap-4 bg-line/30 p-6">
<p className="uppercase font-bold text-lg mb-1.5">
product reviews ({judgemeReviews.reviewNumber})
</p>
<div className="flex justify-start items-center gap-3">
<h4 className="font-medium">{judgemeReviews.rating.toFixed(1)}</h4>
<StarRating rating={judgemeReviews.rating} />
</div>
<div className="mb-4">
<label htmlFor="email" className="block text-gray-700 font-bold mb-2">
Your email
</label>
<input
type="text"
id="email"
name="email"
required
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
/>
</div>
<div className="mb-4">
<label htmlFor="title" className="block text-gray-700 font-bold mb-2">
Review title
</label>
<input
type="text"
id="title"
name="title"
required
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
/>
</div>
<div className="mb-4">
<label htmlFor="body" className="block text-gray-700 font-bold mb-2">
Your review
</label>
<textarea
id="body"
name="body"
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
rows={4}
></textarea>
</div>

<Button
type="submit"
loading={fetcher.state === "submitting"}
disabled={!submitable}
onClick={() => setIsFormVisible(true)} // Show form
disabled={isFormVisible || isPopupVisible}
variant={"outline"}
>
Submit Review
WRITE A REVIEW
</Button>
</fetcher.Form>
{message && (
<div className="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-6">
<p>{message}</p>
</div>
{isFormVisible && (
<div className="bg-line/30 p-6 flex flex-col gap-4">
<div className="flex flex-col gap-3">
<span className="text-base font-bold">Rating</span>
<div className="flex items-center">
{[...Array(5)].map((_, index) => {
const ratingValue = index + 1;
return (
<div
key={index}
onClick={() => handleRatingClick(ratingValue)}
onMouseEnter={() => setHover(ratingValue)}
onMouseLeave={() => setHover(0)}
aria-label={`Rate ${ratingValue} out of 5 stars`}
role="button"
>
{ratingValue <= (hover || rating) ? (
<IconStarFilled />
) : (
<IconStar />
)}
</div>
);
})}
<span className="text-gray-600 ml-3">{rating} out of 5</span>
</div>
</div>
{/* Review Form */}
<fetcher.Form
onSubmit={handleSubmit}
ref={formRef}
method="POST"
encType="multipart/form-data"
>
<input type="hidden" name="rating" value={rating} />
<input type="hidden" name="id" value={internalId} />
<div className="mb-4">
<label
htmlFor="name"
className="block text-gray-700 font-bold mb-2"
>
Your name
</label>
<input
required
type="text"
id="name"
name="name"
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
/>
</div>
<div className="mb-4">
<label
htmlFor="email"
className="block text-gray-700 font-bold mb-2"
>
Your email
</label>
<input
type="email"
id="email"
name="email"
required
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
/>
</div>
<div className="mb-4">
<label
htmlFor="title"
className="block text-gray-700 font-bold mb-2"
>
Review title
</label>
<input
type="text"
id="title"
name="title"
required
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
/>
</div>
<div className="mb-4">
<label
htmlFor="body"
className="block text-gray-700 font-bold mb-2"
>
Your review
</label>
<textarea
id="body"
name="body"
className="w-full border px-3 py-3 border-line/30 outline-none focus-visible:border-line"
rows={4}
></textarea>
</div>
{message && (
<div className="bg-red-100 border-l-4 border-red-500 text-red-700 py-1 px-2 mb-6 flex gap-1 w-fit">
<p className="font-semibold">ERROR:</p>
<p>{message}</p>
</div>
)}
<div className="flex gap-3 justify-end">
<Button
onClick={() => setIsFormVisible(false)}
variant={"outline"}
className="!border-none bg-background"
>
Close
</Button>
<Button
type="submit"
loading={fetcher.state === "submitting"}
disabled={!submitable}
>
Submit Review
</Button>
</div>
</fetcher.Form>
</div>
)}
{submitSuccess && (
<div
className="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-6"
role="alert"
>
<p>Thank you for your review! It has been submitted successfully.</p>
{isPopupVisible && (
<div className="flex flex-col gap-6 p-6 bg-line/30" role="alert">
<p className="font-bold leading-normal text-lg">REVIEW SUBMITTED</p>
<p className="font-normal leading-normal text-base">
Thanks for leaving your review!
</p>
<div className="flex justify-end items-center">
<Button
onClick={() => {
setIsPopupVisible(false);
}}
variant={"outline"}
className="!border-none bg-background"
>
Close
</Button>
</div>
</div>
)}
</div>
);
});
}

export default ReviewForm;

export let schema: HydrogenComponentSchema = {
type: "judgeme-review--form",
title: "Judgeme Review form",
inspector: [
{
group: "Review form",
inputs: [],
},
],
};
Loading

0 comments on commit 5fadc73

Please sign in to comment.