Seed shelf UI: source links, lots, and what's left (#51) (#68)
Build image / build-and-push (push) Successful in 11s
Build image / build-and-push (push) Successful in 11s
Co-authored-by: Steve Dudenhoeffer <[email protected]>
This commit was merged in pull request #68.
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
type PlantCategory,
|
||||
type PlantInput,
|
||||
} from '@/lib/plants'
|
||||
import { safeExternalUrl } from '@/lib/seedLots'
|
||||
import { cmFromSpacing, spacingFromCm, spacingUnitLabel, type UnitPref } from '@/lib/units'
|
||||
|
||||
const DEFAULT_COLOR = '#4a7c3f'
|
||||
@@ -61,6 +62,8 @@ export function PlantFormModal({
|
||||
const [color, setColor] = useState(expandHex(source?.color ?? DEFAULT_COLOR))
|
||||
const [icon, setIcon] = useState(source?.icon ?? DEFAULT_ICON)
|
||||
const [days, setDays] = useState(source?.daysToMaturity != null ? String(source.daysToMaturity) : '')
|
||||
const [sourceUrl, setSourceUrl] = useState(source?.sourceUrl ?? '')
|
||||
const [vendor, setVendor] = useState(source?.vendor ?? '')
|
||||
const [notes, setNotes] = useState(source?.notes ?? '')
|
||||
const [version, setVersion] = useState(plant?.version ?? 0)
|
||||
const [conflict, setConflict] = useState<string | null>(null)
|
||||
@@ -96,6 +99,14 @@ export function PlantFormModal({
|
||||
daysToMaturity = d
|
||||
}
|
||||
|
||||
// The server refuses anything that isn't http(s) with a host, but say so here
|
||||
// rather than letting a paste of "johnnyseeds.com" come back as a generic
|
||||
// error with no hint about which field or why.
|
||||
if (sourceUrl.trim() && !safeExternalUrl(sourceUrl.trim())) {
|
||||
setFormError('The source link needs to be a full http:// or https:// address.')
|
||||
return
|
||||
}
|
||||
|
||||
const input: PlantInput = {
|
||||
name: name.trim(),
|
||||
category,
|
||||
@@ -103,6 +114,8 @@ export function PlantFormModal({
|
||||
color,
|
||||
icon: icon.trim(),
|
||||
daysToMaturity,
|
||||
sourceUrl: sourceUrl.trim(),
|
||||
vendor: vendor.trim(),
|
||||
notes: notes.trim(),
|
||||
}
|
||||
|
||||
@@ -194,6 +207,27 @@ export function PlantFormModal({
|
||||
onChange={(e) => setDays(e.target.value)}
|
||||
/>
|
||||
|
||||
{/* Provenance for the variety itself. What you bought and what's left
|
||||
of it is a seed lot, added from the plant card. */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<TextField
|
||||
label="Vendor"
|
||||
name="vendor"
|
||||
placeholder="Johnny's Selected Seeds"
|
||||
value={vendor}
|
||||
onChange={(e) => setVendor(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
label="Source link"
|
||||
name="sourceUrl"
|
||||
type="url"
|
||||
inputMode="url"
|
||||
placeholder="https://…"
|
||||
value={sourceUrl}
|
||||
onChange={(e) => setSourceUrl(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TextArea label="Notes" name="notes" rows={2} value={notes} onChange={(e) => setNotes(e.target.value)} />
|
||||
|
||||
{formError && <Alert>{formError}</Alert>}
|
||||
|
||||
Reference in New Issue
Block a user