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))} ) })