Added missing bird
This commit is contained in:
@@ -176,6 +176,13 @@ type AuthFormState = {
|
||||
email: string;
|
||||
};
|
||||
|
||||
type LostBirdReportFormState = {
|
||||
tagId: string;
|
||||
finderEmail: string;
|
||||
foundLocation: string;
|
||||
message: string;
|
||||
};
|
||||
|
||||
type AuthNotice = {
|
||||
message: string;
|
||||
previewUrl?: string | null;
|
||||
@@ -280,6 +287,13 @@ const emptyAuthForm: AuthFormState = {
|
||||
email: '',
|
||||
};
|
||||
|
||||
const emptyLostBirdReportForm: LostBirdReportFormState = {
|
||||
tagId: '',
|
||||
finderEmail: '',
|
||||
foundLocation: '',
|
||||
message: '',
|
||||
};
|
||||
|
||||
const emptyIntegrationTokenForm: IntegrationTokenFormState = {
|
||||
name: '',
|
||||
scope: 'read_write',
|
||||
@@ -867,6 +881,9 @@ function App() {
|
||||
const [authNotice, setAuthNotice] = useState<AuthNotice | null>(null);
|
||||
const [authLoading, setAuthLoading] = useState(true);
|
||||
const [authSubmitting, setAuthSubmitting] = useState(false);
|
||||
const [lostBirdReportForm, setLostBirdReportForm] = useState<LostBirdReportFormState>(emptyLostBirdReportForm);
|
||||
const [lostBirdReportNotice, setLostBirdReportNotice] = useState<{ message: string; kind: 'success' | 'error' } | null>(null);
|
||||
const [lostBirdReportSubmitting, setLostBirdReportSubmitting] = useState(false);
|
||||
const [workspace, setWorkspace] = useState<Workspace | null>(null);
|
||||
const [activeMembership, setActiveMembership] = useState<WorkspaceMember | null>(null);
|
||||
const [workspaceMembers, setWorkspaceMembers] = useState<WorkspaceMember[]>([]);
|
||||
@@ -1533,6 +1550,43 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLostBirdReportSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
setLostBirdReportNotice(null);
|
||||
setLostBirdReportSubmitting(true);
|
||||
|
||||
try {
|
||||
const response = await apiFetch('/lost-bird/report', undefined, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
tagId: lostBirdReportForm.tagId.trim(),
|
||||
finderEmail: lostBirdReportForm.finderEmail.trim(),
|
||||
foundLocation: lostBirdReportForm.foundLocation.trim(),
|
||||
message: lostBirdReportForm.message.trim(),
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(await readErrorMessage(response, 'Unable to send this report right now.'));
|
||||
}
|
||||
|
||||
const data = (await readJsonSafely<{ message?: string }>(response)) ?? {};
|
||||
setLostBirdReportNotice({
|
||||
message: data.message ?? 'Report received.',
|
||||
kind: 'success',
|
||||
});
|
||||
setLostBirdReportForm(emptyLostBirdReportForm);
|
||||
} catch (reportError) {
|
||||
setLostBirdReportNotice({
|
||||
message: reportError instanceof Error ? reportError.message : 'Unable to send this report right now.',
|
||||
kind: 'error',
|
||||
});
|
||||
} finally {
|
||||
setLostBirdReportSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
setError('');
|
||||
|
||||
@@ -2610,6 +2664,57 @@ function App() {
|
||||
<p className="muted">
|
||||
Keep every bird's care story in one place; your flock's health, history, and routines together and easier to visualize.
|
||||
</p>
|
||||
<details className="summary-card lost-bird-login-card">
|
||||
<summary>
|
||||
<span>
|
||||
<span className="eyebrow">Report a missing bird</span>
|
||||
</span>
|
||||
</summary>
|
||||
<p className="muted">Enter the band ID and FlockPal will notify the flock if that bird is in the system.</p>
|
||||
<form className="form-panel" onSubmit={handleLostBirdReportSubmit}>
|
||||
<label>
|
||||
Bird band ID
|
||||
<input
|
||||
value={lostBirdReportForm.tagId}
|
||||
onChange={(event) => setLostBirdReportForm({ ...lostBirdReportForm, tagId: event.target.value })}
|
||||
placeholder="Example: ABC-123"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
Your email
|
||||
<input
|
||||
type="email"
|
||||
value={lostBirdReportForm.finderEmail}
|
||||
onChange={(event) => setLostBirdReportForm({ ...lostBirdReportForm, finderEmail: event.target.value })}
|
||||
placeholder="Optional, but helpful"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
Where was the bird found?
|
||||
<input
|
||||
value={lostBirdReportForm.foundLocation}
|
||||
onChange={(event) => setLostBirdReportForm({ ...lostBirdReportForm, foundLocation: event.target.value })}
|
||||
placeholder="City, neighborhood, or nearby landmark"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
Message for the flock
|
||||
<textarea
|
||||
value={lostBirdReportForm.message}
|
||||
onChange={(event) => setLostBirdReportForm({ ...lostBirdReportForm, message: event.target.value })}
|
||||
placeholder="Add any safe details that could help the flock contact you."
|
||||
rows={3}
|
||||
/>
|
||||
</label>
|
||||
<button className="primary-button" type="submit" disabled={lostBirdReportSubmitting}>
|
||||
{lostBirdReportSubmitting ? 'Sending report...' : 'Notify the flock'}
|
||||
</button>
|
||||
</form>
|
||||
{lostBirdReportNotice ? (
|
||||
<p className={lostBirdReportNotice.kind === 'error' ? 'error-banner' : 'success-banner'}>{lostBirdReportNotice.message}</p>
|
||||
) : null}
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div className="auth-card">
|
||||
@@ -2676,6 +2781,7 @@ function App() {
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user