Allow editing SKU value from the Edit SKU modal
Build and push image / build (push) Successful in 54s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-08 15:19:43 -04:00
parent 00a76a10d7
commit 82a72805cf
3 changed files with 26 additions and 7 deletions
+13 -4
View File
@@ -91,6 +91,7 @@ productsRouter.post("/products", (req, res) => {
}); });
type UpdateBody = Partial<{ type UpdateBody = Partial<{
sku: string;
type: string; type: string;
kind: "bulk" | "discrete"; kind: "bulk" | "discrete";
strainId: string | null; strainId: string | null;
@@ -105,13 +106,21 @@ productsRouter.patch("/products/:id", (req, res) => {
const existing = db const existing = db
.prepare< .prepare<
[string], [string],
{ id: string; type: string; kind: string; strain_id: string; brand_id: string | null } { id: string; sku: string; type: string; kind: string; strain_id: string; brand_id: string | null }
>( >(
`SELECT id, type, kind, strain_id, brand_id FROM products WHERE id = ?`, `SELECT id, sku, type, kind, strain_id, brand_id FROM products WHERE id = ?`,
) )
.get(id); .get(id);
if (!existing) return res.status(404).json({ error: "product not found" }); if (!existing) return res.status(404).json({ error: "product not found" });
const nextSku = typeof body.sku === "string" && body.sku.trim() ? body.sku.trim() : existing.sku;
if (nextSku !== existing.sku) {
const duplicate = db
.prepare<[string, string], { id: string }>("SELECT id FROM products WHERE sku = ? AND id != ?")
.get(nextSku, id);
if (duplicate) return res.status(409).json({ error: "sku already exists" });
}
const nextType = typeof body.type === "string" && body.type ? body.type : existing.type; const nextType = typeof body.type === "string" && body.type ? body.type : existing.type;
const nextKind: "bulk" | "discrete" = const nextKind: "bulk" | "discrete" =
body.kind === "bulk" || body.kind === "discrete" body.kind === "bulk" || body.kind === "discrete"
@@ -144,8 +153,8 @@ productsRouter.patch("/products/:id", (req, res) => {
} }
db.prepare( db.prepare(
`UPDATE products SET type = ?, kind = ?, strain_id = ?, brand_id = ? WHERE id = ?`, `UPDATE products SET sku = ?, type = ?, kind = ?, strain_id = ?, brand_id = ? WHERE id = ?`,
).run(nextType, nextKind, nextStrainId, nextBrandId, id); ).run(nextSku, nextType, nextKind, nextStrainId, nextBrandId, id);
res.json({ ok: true }); res.json({ ok: true });
}); });
+1
View File
@@ -38,6 +38,7 @@ export const api = {
updateProduct: ( updateProduct: (
id: string, id: string,
body: Partial<{ body: Partial<{
sku: string;
type: string; type: string;
kind: "bulk" | "discrete"; kind: "bulk" | "discrete";
strainId: string | null; strainId: string | null;
+12 -3
View File
@@ -169,6 +169,7 @@ export function EditSkuModal({
const qc = useQueryClient(); const qc = useQueryClient();
const strain = data.strains.find((s) => s.id === product.strainId); const strain = data.strains.find((s) => s.id === product.strainId);
const [skuValue, setSkuValue] = useState(product.sku);
const [strainName, setStrainName] = useState(strain?.name ?? ""); const [strainName, setStrainName] = useState(strain?.name ?? "");
const [brandId, setBrandId] = useState(product.brandId ?? ""); const [brandId, setBrandId] = useState(product.brandId ?? "");
const [typeId, setTypeId] = useState(product.type); const [typeId, setTypeId] = useState(product.type);
@@ -188,6 +189,7 @@ export function EditSkuModal({
const updateProduct = useMutation({ const updateProduct = useMutation({
mutationFn: async () => { mutationFn: async () => {
await api.updateProduct(product.id, { await api.updateProduct(product.id, {
sku: skuValue.trim(),
type: typeId, type: typeId,
kind: selectedType.kind, kind: selectedType.kind,
strainName: strainName.trim(), strainName: strainName.trim(),
@@ -221,11 +223,18 @@ export function EditSkuModal({
boxShadow: "var(--shadow-lg)", boxShadow: "var(--shadow-lg)",
}} }}
> >
<ModalHeader title="Edit SKU" eyebrow={`SKU · ${product.sku}`} onClose={onClose} /> <ModalHeader title="Edit SKU" eyebrow="SKU" onClose={onClose} />
<div style={{ padding: 32, display: "grid", gap: 16 }}> <div style={{ padding: 32, display: "grid", gap: 16 }}>
<Field label="Strain name"> <Field label="SKU code">
<Input <Input
autoFocus autoFocus
value={skuValue}
onChange={(e) => setSkuValue(e.target.value)}
placeholder="e.g. SKU-0042"
/>
</Field>
<Field label="Strain name">
<Input
value={strainName} value={strainName}
onChange={(e) => setStrainName(e.target.value)} onChange={(e) => setStrainName(e.target.value)}
placeholder="e.g. Blue Dream" placeholder="e.g. Blue Dream"
@@ -316,7 +325,7 @@ export function EditSkuModal({
<Btn <Btn
variant="primary" variant="primary"
icon="check" icon="check"
disabled={!strainName.trim() || updateProduct.isPending} disabled={!skuValue.trim() || !strainName.trim() || updateProduct.isPending}
onClick={() => updateProduct.mutate()} onClick={() => updateProduct.mutate()}
> >
{updateProduct.isPending ? "Saving..." : "Save changes"} {updateProduct.isPending ? "Saving..." : "Save changes"}