import React, { useState } from 'react' import { useGameStore } from '../store/useGameStore' import { CROPS } from '../constants' import { FieldTool, PlotState } from '../types' const fieldContainerStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', gap: '1rem', padding: '1rem', } const titleStyle: React.CSSProperties = { fontSize: '1.5rem', fontWeight: 'bold', marginBottom: '1rem', textAlign: 'center', } const toolbarStyle: React.CSSProperties = { display: 'flex', gap: '0.5rem', marginBottom: '1rem', justifyContent: 'center', } const getToolButtonStyle = (active: boolean): React.CSSProperties => ({ padding: '0.5rem 1rem', borderRadius: '0.25rem', border: '1px solid #ccc', backgroundColor: active ? '#4ade80' : '#f3f4f6', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '0.5rem', }) const cropSelectionContainerStyle: React.CSSProperties = { display: 'flex', flexWrap: 'wrap', gap: '0.5rem', marginBottom: '1rem', justifyContent: 'center', } const cropSelectionLabelStyle: React.CSSProperties = { width: '100%', textAlign: 'center', fontWeight: 500, marginBottom: '0.5rem', } const getCropButtonStyle = (active: boolean): React.CSSProperties => ({ padding: '0.5rem 1rem', borderRadius: '0.25rem', border: '1px solid #ccc', backgroundColor: active ? '#4ade80' : '#f3f4f6', cursor: 'pointer', }) const speedSelectorContainerStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: '1rem', padding: '0.5rem', backgroundColor: '#f9fafb', borderRadius: '0.5rem', border: '1px solid #e5e7eb', } const speedSelectorLabelStyle: React.CSSProperties = { fontWeight: 500, marginBottom: '0.5rem', } const speedButtonsContainerStyle: React.CSSProperties = { display: 'flex', gap: '0.5rem', } const getSpeedButtonStyle = (active: boolean): React.CSSProperties => ({ padding: '0.5rem 1rem', borderRadius: '0.25rem', border: '1px solid #ccc', backgroundColor: active ? '#4ade80' : '#f3f4f6', cursor: 'pointer', }) const getFieldGridStyle = (size: number): React.CSSProperties => ({ display: 'grid', gridTemplateColumns: `repeat(${size}, 1fr)`, gridTemplateRows: `repeat(${size}, 1fr)`, gap: '0.5rem', width: '100%', maxWidth: '600px', margin: '0 auto', }) const getPlotStyle = (bgColor: string): React.CSSProperties => ({ border: '1px solid #78350f', aspectRatio: '1', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', position: 'relative', cursor: 'pointer', backgroundColor: bgColor, }) const getMoistureIndicatorStyle = (level: number): React.CSSProperties => ({ position: 'absolute', bottom: 0, left: 0, width: '100%', height: `${Math.min(level * 100, 100)}%`, backgroundColor: 'rgba(147, 197, 253, 0.3)', transition: 'height 0.3s', zIndex: 1, }) const getMaturityProgressContainerStyle = (): React.CSSProperties => ({ position: 'absolute', bottom: '10px', left: 0, width: '100%', height: '10px', backgroundColor: 'rgba(0, 0, 0, 0.3)', zIndex: 5, border: '1px solid #000', }) const getMaturityProgressBarStyle = ( progress: number, total: number, ): React.CSSProperties => ({ position: 'absolute', bottom: 0, left: 0, width: `${Math.min((progress / total) * 100, 100)}%`, height: '10px', backgroundColor: '#ff5722', transition: 'width 0.3s', zIndex: 6, boxShadow: '0 0 3px rgba(0, 0, 0, 0.5)', }) const modalOverlayStyle: React.CSSProperties = { position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0, 0, 0, 0.5)', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 1000, } const modalContentStyle: React.CSSProperties = { backgroundColor: 'white', padding: '2rem', borderRadius: '0.5rem', maxWidth: '400px', width: '90%', position: 'relative', } const modalCloseButtonStyle: React.CSSProperties = { position: 'absolute', top: '0.5rem', right: '0.5rem', padding: '0.5rem', border: 'none', background: 'none', cursor: 'pointer', fontSize: '1.5rem', } const plotInfoStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', gap: '1rem', } const plotInfoItemStyle: React.CSSProperties = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0.5rem', backgroundColor: '#f3f4f6', borderRadius: '0.25rem', } interface PlotInfoModalProps { plot: PlotState onClose: () => void } const PlotInfoModal: React.FC = ({ plot, onClose }) => { const formatPercentage = (value: number) => `${Math.round(value * 100)}%` return (
e.stopPropagation()}>

Plot Information

Current Crop: {plot.current ? `${CROPS[plot.current.cropId].name}${ plot.current.mature ? ' (Mature)' : '' }` : 'None'}
Intended Crop: {plot.intended ? CROPS[plot.intended].name : 'None'}
Water Level: {formatPercentage(plot.moisture)}
Fertility Level: {formatPercentage(plot.fertility)}
{plot.current && !plot.current.mature && (
Growth Progress: {formatPercentage( plot.current.progress / CROPS[plot.current.cropId].growthTicks, )}
)}
) } const FieldComponent: React.FC = () => { const { plots, fieldSize, plant, water, harvest, remove, assignCrop, gameSpeed, setGameSpeed, actionCooldown, } = useGameStore() const [selectedCrop, setSelectedCrop] = useState(null) const [selectedTool, setSelectedTool] = useState('mark') const [inspectedPlot, setInspectedPlot] = useState<{ plot: PlotState row: number col: number } | null>(null) const handlePlotClick = (row: number, col: number) => { if (actionCooldown > 0) return switch (selectedTool) { case 'mark': if (selectedCrop) { assignCrop(row, col, selectedCrop) } break case 'plant': plant(row, col) break case 'water': water(row, col) break case 'harvest': harvest(row, col) break case 'remove': remove(row, col) break case 'inspect': setInspectedPlot({ plot: plots[row][col], row, col }) break } } const getBgColor = ( hasCrop: boolean, isMature: boolean, fertility: number, ) => { if (isMature) return '#22c55e' if (hasCrop) return '#86efac' // For empty plots, show fertility level through color // Convert fertility (0-1) to a color between light grey-brown and dark brown const r = Math.floor(146 + (73 - 146) * fertility) // 146 to 73 const g = Math.floor(131 + (47 - 131) * fertility) // 131 to 47 const b = Math.floor(120 + (23 - 120) * fertility) // 120 to 23 return `rgb(${r}, ${g}, ${b})` } const availableSpeeds = [1, 2, 4, 8, 16, 32, 64] const tools: { id: FieldTool; label: string; icon: string }[] = [ { id: 'mark', label: 'Mark', icon: '🎯' }, { id: 'plant', label: 'Plant', icon: '🌱' }, { id: 'water', label: 'Water', icon: '💧' }, { id: 'harvest', label: 'Harvest', icon: '✂️' }, { id: 'remove', label: 'Remove', icon: '🗑️' }, { id: 'inspect', label: 'Inspect', icon: '🔍' }, ] return (

Fields

Game Speed:

{availableSpeeds.map((speed) => ( ))}
{tools.map((tool) => ( ))}
{selectedTool === 'mark' && (

Select a crop to mark:

{Object.values(CROPS).map((crop) => ( ))}
)}
{plots.slice(0, fieldSize).map((row, rowIndex) => row.slice(0, fieldSize).map((plot, colIndex) => { const hasCrop = !!plot.current const isMature = !!plot.current?.mature const bgColor = getBgColor(hasCrop, isMature, plot.fertility) return (
handlePlotClick(rowIndex, colIndex)} > {plot.intended && !plot.current && (
🌱 {CROPS[plot.intended]?.name}
)} {plot.current && (
{plot.current.mature ? '🌿' : '🌱'}{' '} {CROPS[plot.current.cropId]?.name}
)}
{plot.current && !plot.current.mature && (
)}
) }), )}
{inspectedPlot && ( setInspectedPlot(null)} /> )}
) } export default FieldComponent