UNPKG

@jeremyckahn/farmhand

Version:
232 lines (218 loc) 7.33 kB
import React from 'react' import { array, bool, func, object, string } from 'prop-types' import Checkbox from '@mui/material/Checkbox/index.js' import FormControlLabel from '@mui/material/FormControlLabel/index.js' import Tooltip from '@mui/material/Tooltip/index.js' import Typography from '@mui/material/Typography/index.js' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import classNames from 'classnames' import { faHeart as faFullHeart } from '@fortawesome/free-solid-svg-icons' import { faHeart as faEmptyHeart } from '@fortawesome/free-regular-svg-icons' import { COW_COLOR_NAMES } from '../../../strings.js' import { genders } from '../../../enums.js' import { moneyString } from '../../../utils/moneyString.js' import { getCowWeight, getPlayerName, integerString, isCowInBreedingPen, nullArray, } from '../../../utils/index.js' import { memoize } from '../../../utils/memoize.js' import { huggingMachine } from '../../../data/items.js' import Bloodline from '../Bloodline/index.js' import './Subheader.sass' // The extra 0.5 is for rounding up to the next full heart. This allows a fully // happy cow to have full hearts on the beginning of a new day. /** * @param {number} heartIndex * @param {number} numberOfFullHearts */ const isHeartFull = (heartIndex, numberOfFullHearts) => heartIndex + 0.5 < numberOfFullHearts const getCowMapById = memoize( /** * @param {farmhand.state['cowInventory']} cowInventory */ cowInventory => cowInventory.reduce((acc, cow) => { acc[cow.id] = cow return acc }, {}) ) /** * @typedef {Pick< * import("../CowCard.js").CowCardProps, * 'cow' | * 'cowBreedingPen' | * 'cowIdOfferedForTrade' | * 'cowInventory' | * 'handleCowAutomaticHugChange' | * 'handleCowBreedChange' | * 'huggingMachinesRemain' | * 'playerId' * > & { * canCowBeTradedFor: boolean, * cowValue: number, * isCowPurchased: boolean, * }} SubheaderProps */ const Subheader = ( /** @type {SubheaderProps} */ { canCowBeTradedFor, cow, cowBreedingPen, cowIdOfferedForTrade, cowInventory, cowValue, handleCowAutomaticHugChange, handleCowBreedChange, huggingMachinesRemain, playerId, isCowPurchased, } ) => { const numberOfFullHearts = cow.happiness * 10 const isInBreedingPen = isCowInBreedingPen(cow, cowBreedingPen) const isRoomInBreedingPen = cowBreedingPen.cowId1 === null || cowBreedingPen.cowId2 === null const isThisCowOfferedForTrade = cowIdOfferedForTrade === cow.id const mateId = cowBreedingPen.cowId1 ?? cowBreedingPen.cowId2 const mate = getCowMapById(cowInventory)[mateId ?? ''] const isEligibleToBreed = cow.gender !== mate?.gender const canBeMovedToBreedingPen = isRoomInBreedingPen && isEligibleToBreed && !isThisCowOfferedForTrade const disableBreedingControlTooltip = !canBeMovedToBreedingPen && !isInBreedingPen const showOriginalOwner = isCowPurchased && playerId !== cow.originalOwnerId && playerId === cow.ownerId return ( <div {...{ className: 'Subheader' }}> <Bloodline {...{ colorsInBloodline: cow.colorsInBloodline }} /> {(isCowPurchased || cowIdOfferedForTrade) && ( <p> {cow.daysOld} {cow.daysOld === 1 ? 'day' : 'days'} old </p> )} <p>Color: {COW_COLOR_NAMES[cow.color]}</p> <p> {/* cow.originalOwnerId is only an empty string when it is for sale. */} {cow.originalOwnerId === '' ? 'Price' : 'Value'}:{' '} {moneyString(cowValue)} </p> <p>Weight: {getCowWeight(cow)} lbs.</p> {(isCowPurchased || canCowBeTradedFor) && ( <p>Times traded: {integerString(cow.timesTraded)}</p> )} {showOriginalOwner && ( <p> Original owner: <strong>{getPlayerName(cow.originalOwnerId)}</strong> </p> )} {isCowPurchased && ( <> <ol className="hearts"> {nullArray(10).map((_null, i) => ( <li key={`${cow.id}_${i}`}> <FontAwesomeIcon {...{ icon: isHeartFull(i, numberOfFullHearts) ? faFullHeart : faEmptyHeart, className: classNames('heart', { 'is-full': isHeartFull(i, numberOfFullHearts), }), }} /> </li> ))} </ol> <Tooltip {...{ arrow: true, placement: 'top', title: ( <Typography> Check this box to put {cow.name} into a {huggingMachine.name}{' '} and automatically hug them at the start of every day. Requires a Hugging Machine in your inventory. </Typography> ), }} > <FormControlLabel {...{ control: ( <Checkbox {...{ color: 'primary', checked: cow.isUsingHuggingMachine, onChange: e => handleCowAutomaticHugChange && handleCowAutomaticHugChange(e, cow), }} /> ), disabled: !cow.isUsingHuggingMachine && !huggingMachinesRemain, label: 'Hug automatically', }} /> </Tooltip> <Tooltip {...{ arrow: true, placement: 'top', disableFocusListener: disableBreedingControlTooltip, disableHoverListener: disableBreedingControlTooltip, disableTouchListener: disableBreedingControlTooltip, title: ( <Typography> {isInBreedingPen ? `Uncheck this box to return ${cow.name} to the regular pen.` : `Check this box to move ${ cow.name } to the breeding pen to mate with a ${ cow.gender === genders.MALE ? 'female' : 'male' } cow.`} </Typography> ), }} > <FormControlLabel {...{ control: ( <Checkbox {...{ color: 'primary', checked: isInBreedingPen, onChange: e => handleCowBreedChange && handleCowBreedChange(e, cow), }} /> ), disabled: isInBreedingPen ? false : !canBeMovedToBreedingPen, label: 'Breed', }} /> </Tooltip> </> )} </div> ) } export default Subheader Subheader.propTypes = { canCowBeTradedFor: bool.isRequired, cow: object.isRequired, cowBreedingPen: object.isRequired, cowIdOfferedForTrade: string.isRequired, cowInventory: array.isRequired, handleCowAutomaticHugChange: func, handleCowBreedChange: func, huggingMachinesRemain: bool.isRequired, playerId: string.isRequired, isCowPurchased: bool, }