import React, { Component } from 'react'
import styled, { css } from 'styled-components'
import { range } from 'fp-ts/lib/Array'
import { Icon } from '@monorail/visualComponents/icon/Icon'
export enum Size {
Tiny = '10',
Small = '16',
Medium = '24',
Large = '32',
}
export enum Fill {
Black = '#000000',
Gold = '#FFC107',
Grey = '#DADADA',
}
const StyledStar = styled.span<{ isEditing?: boolean; interactFill?: Fill }>(
({ isEditing, interactFill }) =>
isEditing &&
interactFill &&
css`
svg {
path {
fill: ${interactFill} !important;
}
}
`,
)
const RatingWrapper = styled.div<{
fill: Fill
isEditing: boolean
spreadOut: boolean
}>(
({ isEditing, spreadOut, fill }) => css`
display: flex;
${isEditing &&
css`
cursor: pointer;
`};
svg {
path {
fill: ${fill};
}
}
${StyledStar} {
${spreadOut &&
css`
margin-right: 10px;
`};
}
`,
)
type StarIcon = 'star_outline' | 'star_half' | 'star_filled'
const handleNever = (err: string): never => {
throw Error(err)
}
export const getRatingIcons = (rating: number): Array<[number, StarIcon]> => {
return range(1, 5).map(value => {
if (rating <= value - 1) {
return [value, 'star_outline']
} else if (rating < value && rating > value - 1) {
return [value, 'star_half']
} else if (rating >= value) {
return [value, 'star_filled']
}
throw Error("Rating could not be determined. This shouldn't happen")
})
}
type Props = {
rating: number
size?: Size
fill?: Fill
interactFill?: Fill
spreadOut?: boolean
onClickRating?: (value: number) => void
}
export const Rating = React.memo((props: Props) => {
const { rating, size, fill, interactFill, spreadOut, onClickRating } = {
size: Size.Small,
fill: Fill.Gold,
interactFill: Fill.Gold,
spreadOut: false,
...props,
}
const getStar = (icon: StarIcon, value: number) => {
switch (icon) {
case 'star_outline':
return (
{
onClickRating && onClickRating(value)
}}
>
)
case 'star_half':
return (
onClickRating && onClickRating(value)}
>
)
case 'star_filled':
return (
onClickRating && onClickRating(value)}
>
)
default:
return handleNever('Unknown star Icon')
}
}
return (
{getRatingIcons(rating).map(([value, icon]) => getStar(icon, value))}
)
})