Files
growstuff/app/javascript/components/PlantingRow.jsx
T
Brenda WallaceandClaude Sonnet 5 a05df8546f Colour progress bars by how the planting is getting on
Blue while growing, green while harvesting, amber when late, red when very
late, grey when finished. The track is now neutral grey so every colour
reads against it. Planting#progress_state decides, and the garden cards,
planting progress and timeline bars use it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 21:08:52 +12:00

70 lines
2.5 KiB
React

import React from 'react';
import {formatDate} from '../dates';
import ActionsMenu from './ActionsMenu';
import CropChip from './CropChip';
// One annual planting as a row of three aligned columns: the crop (and when it
// was planted), how it is getting on (badges, then a progress bar or a note
// when there is nothing to predict from), and its own actions menu.
export default function PlantingRow({planting, defaultIconUrl, highlighted}) {
const {id, url, crop, badges, planted_at: plantedAt} = planting;
return (
<div className={`planting-row${highlighted ? ' planting-just-added' : ''}`}>
<div className="planting-row-crop">
<CropChip url={url} crop={crop} defaultIconUrl={defaultIconUrl} highlighted={highlighted} />
{plantedAt && <span className="planting-row-planted">Planted {formatDate(plantedAt)}</span>}
</div>
<div className="planting-row-status">
{badges.length > 0 && (
<div className="planting-badges">
{badges.map((badge) => (
<span key={badge.kind} className={`badge text-bg-info badge-${badge.kind.replace('_', '-')}`} title={badge.title}>
{badge.label}
</span>
))}
</div>
)}
{planting.progress_note ? (
<small className="planting-row-note">{planting.progress_note}</small>
) : (
<Progress percentage={planting.percentage_grown} state={planting.progress_state} finishLabel={planting.finish_predicted_label} />
)}
</div>
<div className="planting-row-actions">
<ActionsMenu
id={`planting-${id}`}
actions={planting.actions}
label={<i className="fa fa-ellipsis-v" aria-hidden="true" />}
ariaLabel={`Actions for ${crop.name}`}
className="btn btn-sm btn-link planting-actions-toggle"
/>
</div>
</div>
);
}
function Progress({percentage, state, finishLabel}) {
if (percentage === null || percentage === undefined) return null;
return (
<div className="planting-progress">
<div className="progress">
<div
className={`progress-bar progress-bar--${state}`}
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow={percentage}
style={{width: `${percentage}%`}}
/>
</div>
<div className="planting-progress-labels">
<span>{Math.round(percentage)}%</span>
{finishLabel && <span>{finishLabel}</span>}
</div>
</div>
);
}