admin: add and rename bars
This commit is contained in:
parent
1442fbae75
commit
02c7e9b5fd
2 changed files with 81 additions and 15 deletions
|
|
@ -194,6 +194,7 @@ function Drinks() {
|
||||||
function Bars() {
|
function Bars() {
|
||||||
const [bars, setBars] = useState<BarRow[]>([]);
|
const [bars, setBars] = useState<BarRow[]>([]);
|
||||||
const [drinks, setDrinks] = useState<Drink[]>([]);
|
const [drinks, setDrinks] = useState<Drink[]>([]);
|
||||||
|
const [newName, setNewName] = useState('');
|
||||||
|
|
||||||
function reload() {
|
function reload() {
|
||||||
fetch('/admin/api/bars').then(j).then(setBars);
|
fetch('/admin/api/bars').then(j).then(setBars);
|
||||||
|
|
@ -202,11 +203,28 @@ function Bars() {
|
||||||
useEffect(reload, []);
|
useEffect(reload, []);
|
||||||
|
|
||||||
async function patch(id: number, body: Partial<BarRow>) {
|
async function patch(id: number, body: Partial<BarRow>) {
|
||||||
await fetch(`/admin/api/bars/${id}`, {
|
const res = await fetch(`/admin/api/bars/${id}`, {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
});
|
});
|
||||||
|
if (!res.ok) alert(`Fehler: ${await res.text()}`);
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addBar() {
|
||||||
|
const name = newName.trim();
|
||||||
|
if (!name) return;
|
||||||
|
const res = await fetch('/admin/api/bars', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name, pfand_cents: 200 }),
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
alert(`Fehler: ${await res.text()}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setNewName('');
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,7 +234,13 @@ function Bars() {
|
||||||
{bars.map(b => (
|
{bars.map(b => (
|
||||||
<div key={b.id} style="margin-bottom:16px; padding:8px; border:1px solid #333; border-radius:6px">
|
<div key={b.id} style="margin-bottom:16px; padding:8px; border:1px solid #333; border-radius:6px">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<strong>{b.name}</strong>
|
<label>
|
||||||
|
Name
|
||||||
|
<input
|
||||||
|
value={b.name}
|
||||||
|
onChange={(e: any) => patch(b.id, { name: e.currentTarget.value } as any)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Pfand €
|
Pfand €
|
||||||
<input
|
<input
|
||||||
|
|
@ -251,6 +275,14 @@ function Bars() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<div class="row">
|
||||||
|
<input
|
||||||
|
placeholder="Neue Bar"
|
||||||
|
value={newName}
|
||||||
|
onInput={(e: any) => setNewName(e.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
<button onClick={addBar}>Bar hinzufügen</button>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,24 +89,58 @@ export function registerAdminRoutes(app: FastifyInstance, db: DB) {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
app.patch<{ Params: { id: string }; Body: { pfand_cents?: number; drink_ids?: number[] } }>(
|
app.post<{ Body: { name: string; pfand_cents?: number } }>(
|
||||||
|
'/admin/api/bars',
|
||||||
|
async (req, reply) => {
|
||||||
|
if (!requireAuth(req, reply)) return;
|
||||||
|
const name = req.body?.name?.trim();
|
||||||
|
const pfand_cents = req.body?.pfand_cents ?? 0;
|
||||||
|
if (!name) return reply.code(400).send({ error: 'name required' });
|
||||||
|
try {
|
||||||
|
const info = db
|
||||||
|
.prepare('INSERT INTO bars (name, pfand_cents) VALUES (?, ?)')
|
||||||
|
.run(name, pfand_cents);
|
||||||
|
return { id: Number(info.lastInsertRowid) };
|
||||||
|
} catch (e: any) {
|
||||||
|
if (String(e.message).includes('UNIQUE')) {
|
||||||
|
return reply.code(409).send({ error: 'name already exists' });
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
app.patch<{ Params: { id: string }; Body: { name?: string; pfand_cents?: number; drink_ids?: number[] } }>(
|
||||||
'/admin/api/bars/:id',
|
'/admin/api/bars/:id',
|
||||||
async (req, reply) => {
|
async (req, reply) => {
|
||||||
if (!requireAuth(req, reply)) return;
|
if (!requireAuth(req, reply)) return;
|
||||||
const id = Number(req.params.id);
|
const id = Number(req.params.id);
|
||||||
const { pfand_cents, drink_ids } = req.body ?? {};
|
const { name, pfand_cents, drink_ids } = req.body ?? {};
|
||||||
db.transaction(() => {
|
try {
|
||||||
if (pfand_cents !== undefined) {
|
db.transaction(() => {
|
||||||
db.prepare('UPDATE bars SET pfand_cents = ? WHERE id = ?').run(pfand_cents, id);
|
if (name !== undefined) {
|
||||||
|
const trimmed = name.trim();
|
||||||
|
if (!trimmed) throw new Error('name empty');
|
||||||
|
db.prepare('UPDATE bars SET name = ? WHERE id = ?').run(trimmed, id);
|
||||||
|
}
|
||||||
|
if (pfand_cents !== undefined) {
|
||||||
|
db.prepare('UPDATE bars SET pfand_cents = ? WHERE id = ?').run(pfand_cents, id);
|
||||||
|
}
|
||||||
|
if (Array.isArray(drink_ids)) {
|
||||||
|
db.prepare('DELETE FROM bar_drinks WHERE bar_id = ?').run(id);
|
||||||
|
const ins = db.prepare(
|
||||||
|
'INSERT INTO bar_drinks (bar_id, drink_id, sort_order) VALUES (?, ?, ?)'
|
||||||
|
);
|
||||||
|
drink_ids.forEach((did, idx) => ins.run(id, did, idx));
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
} catch (e: any) {
|
||||||
|
if (String(e.message).includes('UNIQUE')) {
|
||||||
|
return reply.code(409).send({ error: 'name already exists' });
|
||||||
}
|
}
|
||||||
if (Array.isArray(drink_ids)) {
|
if (e.message === 'name empty') return reply.code(400).send({ error: 'name empty' });
|
||||||
db.prepare('DELETE FROM bar_drinks WHERE bar_id = ?').run(id);
|
throw e;
|
||||||
const ins = db.prepare(
|
}
|
||||||
'INSERT INTO bar_drinks (bar_id, drink_id, sort_order) VALUES (?, ?, ?)'
|
|
||||||
);
|
|
||||||
drink_ids.forEach((did, idx) => ins.run(id, did, idx));
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue