redhare-demo/components/modals/ReviewModal.jsx

265 lines
8.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

'use client'
import { useState, useRef } from 'react'
import { nanoid } from '@reduxjs/toolkit'
import { useCreateReviewMutation } from '@/store/services'
import { ratingStatus, reviewSchema } from 'utils'
import { SubmitHandler, useFieldArray, useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import { Icons, TextField, DisplayError, SubmitModalBtn, Modal, HandleResponse } from 'components'
const ReviewModal = props => {
//? Props
const { isShow, onClose, productTitle, prdouctID } = props
//? Refs
const positiveRef = useRef(null)
const negativeRef = useRef(null)
//? State
const [rating, setRating] = useState(1)
//? Form Hook
const {
handleSubmit,
register,
formState: { errors: formErrors },
reset,
control,
} = useForm({
resolver: yupResolver(reviewSchema),
defaultValues: {
comment: '',
title: '',
positivePoints: [],
negativePoints: [],
rating: 1,
product: '',
},
})
const {
fields: positivePointsFields,
append: appentPositivePoint,
remove: removePositivePoint,
} = useFieldArray({
name: 'positivePoints',
control,
})
const {
fields: negativePointsFields,
append: appendNegativePoint,
remove: removeNegativePoint,
} = useFieldArray({
name: 'negativePoints',
control,
})
//? Create Review Query
const [createReview, { isSuccess, isLoading, data, isError, error }] = useCreateReviewMutation()
//? Handlers
const handleAddPositivePoint = () => {
if (positiveRef.current) {
appentPositivePoint({ id: nanoid(), title: positiveRef.current.value })
positiveRef.current.value = ''
}
}
const handleAddNegativePoint = () => {
if (negativeRef.current) {
appendNegativePoint({ id: nanoid(), title: negativeRef.current.value })
negativeRef.current.value = ''
}
}
const submitHander = data =>
createReview({
body: { ...data, rating, product: prdouctID },
})
//? Render(s)
return (
<>
{/* Handle Create Review Response */}
{(isSuccess || isError) && (
<HandleResponse
isError={isError}
isSuccess={isSuccess}
error={error?.data?.message}
message={data?.message}
onSuccess={() => {
onClose()
reset()
setRating(1)
}}
onError={() => {
onClose()
reset()
setRating(1)
}}
/>
)}
<Modal isShow={isShow} onClose={onClose} effect="bottom-to-top">
<Modal.Content
onClose={onClose}
className="flex flex-col h-full lg:h-[770px] pl-2 pr-4 py-3 bg-white md:rounded-lg gap-y-3"
>
<Modal.Header onClose={onClose}>留下你对 {productTitle} 商品的评价</Modal.Header>
<Modal.Body>
<form
className="flex flex-col justify-between flex-1 pl-4 overflow-y-auto gap-y-5"
onSubmit={handleSubmit(submitHander)}
>
{/* rating */}
<div>
<div className="my-2 text-center">
<span className="text-sm text-black">评分!:</span>
<span className="px-1 text-sm text-sky-500">{ratingStatus[rating]}</span>
</div>
<input
id="rating"
name="rating"
type="range"
min="1"
max="5"
step="1"
value={rating}
className="w-full h-2 bg-gray-200 rounded-lg cursor-pointer "
onChange={e => {
setRating(+e.target.value)
}}
/>
<div className="flex justify-between">
{Array(5)
.fill('_')
.map((_, i) => (
<span
key={i}
className="h-1 w-1 rounded-full mx-1.5 bg-gray-300 inline-block"
/>
))}
</div>
</div>
{/* title */}
<TextField
label="评价标题"
control={control}
errors={formErrors.title}
name="title"
/>
{/* positivePoints */}
<div className="space-y-3">
<div className="space-y-3">
<label
className="text-xs text-gray-700 lg:text-sm md:min-w-max"
htmlFor="positivePoints"
>
优点
</label>
<div className="flex items-center input">
<input
className="flex-1 bg-transparent outline-none"
type="text"
name="positivePoints"
id="positivePoints"
ref={positiveRef}
/>
<button onClick={handleAddPositivePoint} type="button">
<Icons.Plus className="icon" />
</button>
</div>
</div>
{positivePointsFields.length > 0 && (
<div className="space-y-3">
{positivePointsFields.map((field, index) => (
<div key={field.id} className="flex items-center px-3 gap-x-4">
<Icons.Plus className="text-green-500 icon" />
<span className="ml-auto">{field.title}</span>
<button>
<Icons.Delete
className="icon text-gray"
onClick={() => removePositivePoint(index)}
/>
</button>
</div>
))}
</div>
)}
</div>
{/* negativePoints */}
<div className="space-y-3">
<div className="space-y-3">
<label
className="text-xs text-gray-700 lg:text-sm md:min-w-max"
htmlFor="negativePoints"
>
缺点
</label>
<div className="flex items-center input">
<input
className="flex-1 bg-transparent outline-none"
type="text"
name="negativePoints"
id="negativePoints"
ref={negativeRef}
/>
<button onClick={handleAddNegativePoint} type="button">
<Icons.Plus className="icon" />
</button>
</div>
</div>
{negativePointsFields.length > 0 && (
<div className="space-y-3">
{negativePointsFields.map((field, index) => (
<div key={field.id} className="flex items-center px-3 gap-x-4">
<Icons.Minus className="text-red-500 icon" />
<span className="ml-auto">{field.title}</span>
<button>
<Icons.Delete
className="icon text-gray"
onClick={() => removeNegativePoint(index)}
/>
</button>
</div>
))}
</div>
)}
</div>
{/* comment */}
<div className="space-y-3 ">
<label className="text-xs text-gray-700 lg:text-sm md:min-w-max" htmlFor="comment">
评价文字
</label>
<textarea
className="h-24 resize-none input"
id="comment"
{...register('comment')}
/>
<DisplayError errors={formErrors.comment} />
</div>
<div className="py-3 border-t-2 border-gray-200 lg:pb-0 ">
<SubmitModalBtn isLoading={isLoading}>提交评价</SubmitModalBtn>
</div>
</form>
</Modal.Body>
</Modal.Content>
</Modal>
</>
)
}
export default ReviewModal