import React, {useEffect, useState} from 'react'; import {getJson, patchJson} from '../api'; import Modal from './Modal'; function humanize(field) { return field.replace(/_/g, ' ').replace(/^./, (c) => c.toUpperCase()); } function errorMessages(status, data) { if (status === 422 && data && data.errors) { const messages = Object.entries(data.errors).flatMap(([field, list]) => list.map((m) => `${humanize(field)} ${m}`)); if (messages.length > 0) return messages; } if (status === 401) return ['Please sign in again to save this garden.']; if (status === 403) return ['You can\'t change this garden.']; return ['Something went wrong saving that. Please try again.']; } // The same fields as the garden edit page, in a dialog over the garden list. It // loads the garden's current values from /gardens/:slug/edit.json, saves with // PATCH, and hands the refreshed garden card to onSaved, so the list updates in // place and the page is never left. export default function EditGardenModal({garden, onClose, onSaved}) { const [form, setForm] = useState(null); // {garden, area_units, garden_types, location_help, ...} const [values, setValues] = useState(null); const [loadError, setLoadError] = useState(false); const [saving, setSaving] = useState(false); const [errors, setErrors] = useState([]); useEffect(() => { const controller = new AbortController(); (async () => { try { const {ok, data} = await getJson(`${garden.url}/edit.json`, {signal: controller.signal}); if (!ok) throw new Error('load failed'); setForm(data); setValues(data.garden); } catch (error) { if (error.name !== 'AbortError') setLoadError(true); } })(); return () => controller.abort(); }, [garden.url]); const set = (field) => (event) => { const {type, checked, value} = event.target; setValues((current) => ({...current, [field]: type === 'checkbox' ? checked : value})); }; async function save(event) { event.preventDefault(); setSaving(true); setErrors([]); const {name, description, location, area, area_unit: areaUnit, garden_type_id: gardenTypeId, active} = values; try { const {ok, status, data} = await patchJson(garden.url, { garden: {name, description, location, area, area_unit: areaUnit, garden_type_id: gardenTypeId, active}, }); if (ok) { onSaved(data.garden); // closes this dialog return; } setErrors(errorMessages(status, data)); } catch (error) { setErrors(['Couldn\'t reach the server. Please try again.']); } setSaving(false); } return ( {loadError && (
Couldn’t load this garden. Please close this and try again.
)} {!loadError && !values && (