feat: stránka doplnit údaje předělána na samostatnou stránku jídel + přidáno přejmenování
99 lines
4.0 KiB
TypeScript
99 lines
4.0 KiB
TypeScript
import { useState } from "react";
|
||
import { Alert, Button, Form } from "react-bootstrap";
|
||
import { toast } from "react-toastify";
|
||
import { MealGroup, renameMealGroup } from "../../../types";
|
||
import { getMealKey } from "../Utils";
|
||
import SourceInput from "./SourceInput";
|
||
|
||
type Props = {
|
||
group: MealGroup,
|
||
/** Ostatní skupiny — podle nich se pozná, že se jídla po přejmenování s některou sloučí. */
|
||
groupList: MealGroup[],
|
||
onRenamed: () => void,
|
||
onCancel: () => void,
|
||
};
|
||
|
||
/** Popisek výsledku přejmenování se skloňovaným počtem jídel. */
|
||
const describeRenamed = (count: number): string => {
|
||
if (!count) return 'Název i zdroj už jídla mají, nic se nezměnilo.';
|
||
if (count === 1) return 'Změněno 1 jídlo.';
|
||
if (count < 5) return `Změněna ${count} jídla.`;
|
||
return `Změněno ${count} jídel.`;
|
||
};
|
||
|
||
/**
|
||
* Hromadná změna názvu a zdroje všech jídel jedné skupiny ve všech dnech.
|
||
*
|
||
* Na rozdíl od doplnění údajů přepisuje, proto je to samostatná akce. Když nový
|
||
* název a zdroj patří jiné skupině, jídla se do ní sloučí — formulář na to upozorní.
|
||
*/
|
||
const MealGroupRenameForm = ({ group, groupList, onRenamed, onCancel }: Readonly<Props>) => {
|
||
const [name, setName] = useState(group.name);
|
||
const [source, setSource] = useState(group.source ?? '');
|
||
const [saving, setSaving] = useState(false);
|
||
|
||
const targetKey = getMealKey({ name, source });
|
||
const mergeGroup = targetKey !== getMealKey(group)
|
||
? groupList.find(item => getMealKey(item) === targetKey)
|
||
: undefined;
|
||
const unchanged = name.trim() === group.name && source.trim() === (group.source ?? '');
|
||
const canSave = !!name.trim().length && !unchanged && !saving;
|
||
|
||
const save = async () => {
|
||
if (!canSave) return;
|
||
setSaving(true);
|
||
const response = await renameMealGroup({
|
||
body: {
|
||
name: group.name,
|
||
source: group.source,
|
||
newName: name.trim(),
|
||
...(source.trim().length ? { newSource: source.trim() } : {}),
|
||
},
|
||
});
|
||
setSaving(false);
|
||
if (response.data) {
|
||
toast.success(describeRenamed(response.data.count));
|
||
onRenamed();
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Form className="meal-group-form" onSubmit={event => { event.preventDefault(); save(); }}>
|
||
<p className="text-body-secondary small">
|
||
{group.count === 1
|
||
? 'Změní se jen u tohoto jídla.'
|
||
: `Změní se u všech ${group.count} jídel ve všech dnech, kdy se jedla.`} Ostatní údaje zůstanou.
|
||
</p>
|
||
<div className="row g-3 mb-3">
|
||
<div className="col-sm-7">
|
||
<Form.Label>Název</Form.Label>
|
||
<Form.Control
|
||
autoFocus
|
||
value={name}
|
||
isInvalid={!name.trim().length}
|
||
onChange={event => setName(event.target.value)}
|
||
/>
|
||
</div>
|
||
<div className="col-sm-5">
|
||
<Form.Label>Zdroj</Form.Label>
|
||
<SourceInput value={source} placeholder="bez zdroje" onChange={value => setSource(value)} />
|
||
</div>
|
||
</div>
|
||
{mergeGroup && (
|
||
<Alert variant="warning" className="py-2 small">
|
||
Jídlo „{mergeGroup.name}“{mergeGroup.source ? ` (${mergeGroup.source})` : ' bez zdroje'} už
|
||
v seznamu je ({mergeGroup.count}×), jídla se s ním sloučí.
|
||
</Alert>
|
||
)}
|
||
<div className="d-flex justify-content-end gap-2">
|
||
<Button variant="outline-secondary" onClick={() => onCancel()}>Zrušit</Button>
|
||
<Button type="submit" disabled={!canSave}>
|
||
{saving ? 'Ukládám…' : 'Změnit u všech jídel'}
|
||
</Button>
|
||
</div>
|
||
</Form>
|
||
);
|
||
};
|
||
|
||
export default MealGroupRenameForm;
|