Improved StarRating indication of rated mark

This commit is contained in:
Dmitriy Shishkov 2023-08-09 14:24:44 +03:00
parent 9937708da5
commit 6478b45301
Signed by: dm1sh
GPG Key ID: 027994B0AA357688
2 changed files with 42 additions and 17 deletions

View File

@ -25,10 +25,12 @@ const styles = {
} }
type ViewProps = { type ViewProps = {
myId: number,
announcement: Announcement, announcement: Announcement,
} }
const View = ({ const View = ({
myId,
announcement: { name, category, bestBy, description, lat, lng, address, metro, userId }, announcement: { name, category, bestBy, description, lat, lng, address, metro, userId },
}: ViewProps) => ( }: ViewProps) => (
<> <>
@ -41,7 +43,7 @@ const View = ({
<p className='mb-0'>{description}</p> <p className='mb-0'>{description}</p>
<p className='mb-3'> <p className='mb-3'>
Рейтинг пользователя: <StarRating dynamic userId={userId} /> Рейтинг пользователя: <StarRating dynamic={myId !== userId} userId={userId} />
</p> </p>
<MapContainer style={styles.map} center={[lat, lng]} zoom={16} > <MapContainer style={styles.map} center={[lat, lng]} zoom={16} >
@ -62,12 +64,14 @@ const View = ({
) )
type ControlProps = { type ControlProps = {
myId: number,
closeRefresh: () => void, closeRefresh: () => void,
announcement: Announcement, announcement: Announcement,
showDispose: () => void showDispose: () => void
} }
function Control({ function Control({
myId,
closeRefresh, closeRefresh,
announcement: { bookedBy, id, userId }, announcement: { bookedBy, id, userId },
showDispose, showDispose,
@ -76,8 +80,6 @@ function Control({
const { handleRemove, removeButton } = useRemoveAnnouncement(closeRefresh) const { handleRemove, removeButton } = useRemoveAnnouncement(closeRefresh)
const myId = useId()
return ( return (
<> <>
<p>Забронировали {bookedBy + (bookButton.disabled ? 1 : 0)} чел.</p> <p>Забронировали {bookedBy + (bookButton.disabled ? 1 : 0)} чел.</p>
@ -111,6 +113,8 @@ function AnnouncementDetails({
const [disposeShow, setDisposeShow] = useState(false) const [disposeShow, setDisposeShow] = useState(false)
const myId = useId()
return ( return (
<div <div
className='modal' className='modal'
@ -124,11 +128,16 @@ function AnnouncementDetails({
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<View announcement={announcement} /> <View myId={myId} announcement={announcement} />
</Modal.Body> </Modal.Body>
<Modal.Footer> <Modal.Footer>
<Control closeRefresh={closeRefresh} showDispose={() => setDisposeShow(true)} announcement={announcement} /> <Control
myId={myId}
closeRefresh={closeRefresh}
showDispose={() => setDisposeShow(true)}
announcement={announcement}
/>
</Modal.Footer> </Modal.Footer>
</Modal.Dialog> </Modal.Dialog>
<Modal centered show={disposeShow} onHide={() => setDisposeShow(false)} style={{ zIndex: 100000 }}> <Modal centered show={disposeShow} onHide={() => setDisposeShow(false)} style={{ zIndex: 100000 }}>

View File

@ -8,18 +8,17 @@ import styles from '../styles/StarRating.module.css'
type StarProps = { type StarProps = {
filled: boolean, filled: boolean,
selected: boolean, selected: boolean,
setMyRate?: () => void, selectRate?: () => void,
sendMyRate?: () => void, sendMyRate?: () => void,
disabled: boolean disabled: boolean
} }
function Star({ filled, selected, setMyRate, sendMyRate, disabled }: StarProps) { function Star({ filled, selected, selectRate, disabled }: StarProps) {
return ( return (
<button <button
className={`${styles.star} ${filled ? styles.starFilled : ''} ${selected ? styles.starSelected : ''}`} className={`${styles.star} ${filled ? styles.starFilled : ''} ${selected ? styles.starSelected : ''}`}
onMouseEnter={setMyRate} onMouseEnter={selectRate}
onFocus={setMyRate} onFocus={selectRate}
onClick={sendMyRate}
disabled={disabled} disabled={disabled}
>&#9733;</button> // star >&#9733;</button> // star
) )
@ -28,21 +27,23 @@ function Star({ filled, selected, setMyRate, sendMyRate, disabled }: StarProps)
type StarRatingProps = { type StarRatingProps = {
userId: number, userId: number,
dynamic?: boolean, dynamic?: boolean,
style?: React.CSSProperties,
} }
function StarRating({ userId, dynamic = false }: StarRatingProps) { function StarRating({ userId, dynamic = false }: StarRatingProps) {
const rating = useUserRating(userId) const rating = useUserRating(userId)
const [selectedRate, setSelectedRate] = useState(0)
const [myRate, setMyRate] = useState(0) const [myRate, setMyRate] = useState(0)
const rated = myRate > 0
const { doSendRate } = useSendRate() const { doSendRate } = useSendRate()
async function sendMyRate() { async function sendMyRate() {
const res = await doSendRate(myRate, userId) const res = await doSendRate(selectedRate, userId)
if (res) { if (res) {
rating.refetch() rating.refetch()
setMyRate(selectedRate)
} }
} }
@ -59,15 +60,30 @@ function StarRating({ userId, dynamic = false }: StarRatingProps) {
} }
return ( return (
<span className={styles.starContainer} onMouseLeave={() => setMyRate(0)}> <span
className={styles.starContainer}
onClick={() => dynamic && !rated && void sendMyRate()}
onMouseEnter={() => rated && setSelectedRate(myRate)}
onMouseLeave={() => setSelectedRate(0)}
onFocus={() => rated && setSelectedRate(myRate)}
onBlur={() => setSelectedRate(0)}
onTouchStart={() => rated && setSelectedRate(myRate)}
onTouchEnd={() => setSelectedRate(0)}
title={`Пользователи: ${Math.round(rating.data)}\nВы: ${myRate}`}
tabIndex={0}
>
{...Array(5).fill(5).map((_, i) => ( {...Array(5).fill(5).map((_, i) => (
<Star <Star
key={i} key={i}
filled={i < Math.round(rating.data)} filled={i < Math.round(rating.data)}
selected={i < myRate} selected={i < selectedRate}
setMyRate={() => dynamic && setMyRate(i + 1)} selectRate={() => dynamic && !rated && setSelectedRate(i + 1)}
sendMyRate={() => dynamic && void sendMyRate()} disabled={!dynamic || rated}
disabled={!dynamic}
/> />
))} ))}
</span > </span >