Added gender
This commit is contained in:
+91
-2
@@ -7,6 +7,7 @@ type HouseholdBillingPlan = Exclude<BillingPlan, 'rescue_free'>;
|
||||
type WorkspaceType = 'standard' | 'rescue';
|
||||
type WorkspaceRole = 'owner' | 'manager' | 'staff' | 'viewer';
|
||||
type IntegrationTokenScope = 'read_only' | 'read_write';
|
||||
type BirdGender = 'unknown' | 'male' | 'female';
|
||||
|
||||
type Bird = {
|
||||
id: string;
|
||||
@@ -14,6 +15,7 @@ type Bird = {
|
||||
name: string;
|
||||
tagId: string;
|
||||
species: string;
|
||||
gender: BirdGender;
|
||||
dateOfBirth: string | null;
|
||||
gotchaDay: string | null;
|
||||
chartColor: string;
|
||||
@@ -113,6 +115,7 @@ type BirdFormState = {
|
||||
name: string;
|
||||
tagId: string;
|
||||
species: string;
|
||||
gender: BirdGender;
|
||||
dateOfBirth: string;
|
||||
gotchaDay: string;
|
||||
chartColor: string;
|
||||
@@ -207,6 +210,7 @@ const emptyBirdForm: BirdFormState = {
|
||||
name: '',
|
||||
tagId: '',
|
||||
species: '',
|
||||
gender: 'unknown',
|
||||
dateOfBirth: '',
|
||||
gotchaDay: '',
|
||||
chartColor: '#cb3a35',
|
||||
@@ -303,6 +307,7 @@ const toBirdForm = (bird: Bird): BirdFormState => ({
|
||||
name: bird.name,
|
||||
tagId: bird.tagId,
|
||||
species: bird.species,
|
||||
gender: bird.gender,
|
||||
dateOfBirth: bird.dateOfBirth ?? '',
|
||||
gotchaDay: bird.gotchaDay ?? '',
|
||||
chartColor: bird.chartColor,
|
||||
@@ -334,6 +339,26 @@ const formatShortDate = (value: string | null) => {
|
||||
}).format(new Date(`${value}T00:00:00`));
|
||||
};
|
||||
|
||||
const getBirdGenderLabel = (bird: Pick<Bird, 'gender'>) => {
|
||||
if (bird.gender === 'female') {
|
||||
return 'Female';
|
||||
}
|
||||
if (bird.gender === 'male') {
|
||||
return 'Male';
|
||||
}
|
||||
return 'Unknown';
|
||||
};
|
||||
|
||||
const getBirdGenderSymbol = (bird: Pick<Bird, 'gender'>) => {
|
||||
if (bird.gender === 'female') {
|
||||
return '♀';
|
||||
}
|
||||
if (bird.gender === 'male') {
|
||||
return '♂';
|
||||
}
|
||||
return '?';
|
||||
};
|
||||
|
||||
const formatDateTime = (value: string | null) => {
|
||||
if (!value) {
|
||||
return 'Never';
|
||||
@@ -2376,7 +2401,12 @@ function App() {
|
||||
</div>
|
||||
)}
|
||||
<div className="bird-card-copy">
|
||||
<span>{bird.name}</span>
|
||||
<span className="bird-card-title">
|
||||
<span>{bird.name}</span>
|
||||
<span aria-label={getBirdGenderLabel(bird)} className={`gender-inline ${bird.gender}`}>
|
||||
{getBirdGenderSymbol(bird)}
|
||||
</span>
|
||||
</span>
|
||||
<small>{bird.species}</small>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2482,7 +2512,15 @@ function App() {
|
||||
)}
|
||||
<div className="profile-copy">
|
||||
<p className="eyebrow">Profile</p>
|
||||
<h3>{selectedBird.name}</h3>
|
||||
<h3 className="profile-title">
|
||||
<span>{selectedBird.name}</span>
|
||||
<span
|
||||
aria-label={getBirdGenderLabel(selectedBird)}
|
||||
className={`gender-symbol ${selectedBird.gender}`}
|
||||
>
|
||||
{getBirdGenderSymbol(selectedBird)}
|
||||
</span>
|
||||
</h3>
|
||||
<p className="muted">
|
||||
{selectedBird.species} • Band {selectedBird.tagId}
|
||||
</p>
|
||||
@@ -2511,6 +2549,15 @@ function App() {
|
||||
<span>Species</span>
|
||||
<strong>{selectedBird.species}</strong>
|
||||
</article>
|
||||
<article className="detail-card">
|
||||
<span>Gender</span>
|
||||
<strong className="detail-gender">
|
||||
<span aria-hidden="true" className={`gender-symbol ${selectedBird.gender}`}>
|
||||
{getBirdGenderSymbol(selectedBird)}
|
||||
</span>
|
||||
{getBirdGenderLabel(selectedBird)}
|
||||
</strong>
|
||||
</article>
|
||||
<article className="detail-card">
|
||||
<span>Latest weight</span>
|
||||
<strong>{formatWeight(selectedBird.latestWeightGrams)}</strong>
|
||||
@@ -3206,6 +3253,48 @@ function App() {
|
||||
</div>
|
||||
<small className="muted">Search or select a species so alerts and chart references stay consistent.</small>
|
||||
</label>
|
||||
<div className="segmented-field">
|
||||
<span>Gender</span>
|
||||
<div className="segmented-control" role="radiogroup" aria-label="Bird gender">
|
||||
<button
|
||||
className={`segmented-option ${birdForm.gender === 'unknown' ? 'active' : ''}`}
|
||||
onClick={() => setBirdForm({ ...birdForm, gender: 'unknown' })}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={birdForm.gender === 'unknown'}
|
||||
>
|
||||
<span className="gender-symbol unknown" aria-hidden="true">
|
||||
?
|
||||
</span>
|
||||
Unknown
|
||||
</button>
|
||||
<button
|
||||
className={`segmented-option ${birdForm.gender === 'male' ? 'active' : ''}`}
|
||||
onClick={() => setBirdForm({ ...birdForm, gender: 'male' })}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={birdForm.gender === 'male'}
|
||||
>
|
||||
<span className="gender-symbol male" aria-hidden="true">
|
||||
♂
|
||||
</span>
|
||||
Male
|
||||
</button>
|
||||
<button
|
||||
className={`segmented-option ${birdForm.gender === 'female' ? 'active' : ''}`}
|
||||
onClick={() => setBirdForm({ ...birdForm, gender: 'female' })}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={birdForm.gender === 'female'}
|
||||
>
|
||||
<span className="gender-symbol female" aria-hidden="true">
|
||||
♀
|
||||
</span>
|
||||
Female
|
||||
</button>
|
||||
</div>
|
||||
<small className="muted">Shown on the bird profile card as a symbol.</small>
|
||||
</div>
|
||||
<label>
|
||||
DOB
|
||||
<input
|
||||
|
||||
Reference in New Issue
Block a user