FEAT-5: Probeverpaarung page — free genotype entry, client-side breed(), Farbschlag cards + warnings
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
62
gerbil-manager-web/src/components/ParentSelector.tsx
Normal file
62
gerbil-manager-web/src/components/ParentSelector.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { isValidGenotype, previewFarbschlag } from '../format/genotypeText'
|
||||
import { de } from '../strings/de'
|
||||
|
||||
export interface ParentValue {
|
||||
/** Free-text genotype (GEN-1 compact string; '?' wildcards allowed). */
|
||||
genotype: string
|
||||
/** Name of a picked animal, if the genotype came from one (display only). */
|
||||
animalName?: string | null
|
||||
}
|
||||
|
||||
export interface ParentSelectorProps {
|
||||
label: string
|
||||
value: ParentValue
|
||||
onChange: (value: ParentValue) => void
|
||||
/** Optional animal-picker UI (FEAT-5 increment 3) rendered above the input. */
|
||||
picker?: ReactNode
|
||||
}
|
||||
|
||||
export default function ParentSelector({ label, value, onChange, picker }: ParentSelectorProps) {
|
||||
const t = de.pages.genetik
|
||||
const preview = previewFarbschlag(value.genotype)
|
||||
const invalid = value.genotype.trim() !== '' && !isValidGenotype(value.genotype)
|
||||
|
||||
return (
|
||||
<fieldset className="parent-selector">
|
||||
<legend>{label}</legend>
|
||||
{picker}
|
||||
{value.animalName && (
|
||||
<p className="muted parent-selector__animal">
|
||||
{value.animalName}
|
||||
<button
|
||||
type="button"
|
||||
className="link-btn"
|
||||
onClick={() => onChange({ genotype: '', animalName: null })}
|
||||
>
|
||||
{t.clearAnimal}
|
||||
</button>
|
||||
</p>
|
||||
)}
|
||||
<label className="field">
|
||||
<span>{t.genotypeLabel}</span>
|
||||
<input
|
||||
className="input"
|
||||
value={value.genotype}
|
||||
placeholder="Aa CC Dd EE GG Pp Spsp rere"
|
||||
onChange={(e) => onChange({ genotype: e.target.value, animalName: null })}
|
||||
aria-invalid={invalid}
|
||||
/>
|
||||
{invalid ? (
|
||||
<small className="error-text">{t.genotypeInvalid}</small>
|
||||
) : preview ? (
|
||||
<small className="muted">
|
||||
{t.genotypePreview}: <strong>{preview}</strong>
|
||||
</small>
|
||||
) : (
|
||||
<small className="muted">{t.genotypeHint}</small>
|
||||
)}
|
||||
</label>
|
||||
</fieldset>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user