Vendor-assign events and scope event catalog to vendor
- Add vendorWhereClause() helper: admin + ?vendorId= filters to that vendor; admin with no filter sees all; other roles locked to own - Fix events GET / to use vendorWhereClause so vendor filter works - EventFormModal: admin sees a Vendor picker when creating a new event, pre-populated from the active VendorFilter; POST includes ?vendorId= - EventConfigPanel: scope /taxes and /products fetches to event.vendorId so only the event's vendor's catalog items are selectable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ import { PageHeader } from "../components/PageHeader";
|
||||
import { VendorFilter } from "../components/VendorFilter";
|
||||
import { Table } from "../components/Table";
|
||||
import { Modal } from "../components/Modal";
|
||||
import { FormField, Btn } from "../components/FormField";
|
||||
import { FormField, Btn, inputStyle } from "../components/FormField";
|
||||
|
||||
// ─── Types ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -139,6 +139,7 @@ export default function EventsPage() {
|
||||
{showForm && (
|
||||
<EventFormModal
|
||||
event={editing}
|
||||
defaultVendorId={vendorId}
|
||||
onClose={() => setShowForm(false)}
|
||||
onSaved={() => { setShowForm(false); load(); }}
|
||||
/>
|
||||
@@ -159,20 +160,39 @@ export default function EventsPage() {
|
||||
|
||||
// ─── Event Form Modal ────────────────────────────────────────────────────────
|
||||
|
||||
function EventFormModal({ event, onClose, onSaved }: {
|
||||
function EventFormModal({ event, defaultVendorId, onClose, onSaved }: {
|
||||
event: Event | null;
|
||||
defaultVendorId?: string;
|
||||
onClose: () => void;
|
||||
onSaved: () => void;
|
||||
}) {
|
||||
const { user } = useAuth();
|
||||
const isAdmin = user?.role === "admin";
|
||||
const [name, setName] = useState(event?.name ?? "");
|
||||
const [description, setDescription] = useState(event?.description ?? "");
|
||||
const [startsAt, setStartsAt] = useState(event ? toDatetimeLocal(event.startsAt) : "");
|
||||
const [endsAt, setEndsAt] = useState(event ? toDatetimeLocal(event.endsAt) : "");
|
||||
const [isActive, setIsActive] = useState(event?.isActive ?? true);
|
||||
const [selectedVendorId, setSelectedVendorId] = useState(
|
||||
event?.vendorId ?? defaultVendorId ?? ""
|
||||
);
|
||||
const [vendors, setVendors] = useState<Vendor[]>([]);
|
||||
const [error, setError] = useState("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAdmin && !event) {
|
||||
api.get<{ data: Vendor[] }>("/vendors?limit=200")
|
||||
.then((r) => setVendors(r.data))
|
||||
.catch(console.error);
|
||||
}
|
||||
}, [isAdmin, event]);
|
||||
|
||||
const save = async () => {
|
||||
if (isAdmin && !event && !selectedVendorId) {
|
||||
setError("Please select a vendor for this event.");
|
||||
return;
|
||||
}
|
||||
setSaving(true);
|
||||
setError("");
|
||||
try {
|
||||
@@ -185,7 +205,8 @@ function EventFormModal({ event, onClose, onSaved }: {
|
||||
if (event) {
|
||||
await api.put(`/events/${event.id}`, body);
|
||||
} else {
|
||||
await api.post("/events", body);
|
||||
const q = isAdmin && selectedVendorId ? `?vendorId=${encodeURIComponent(selectedVendorId)}` : "";
|
||||
await api.post(`/events${q}`, body);
|
||||
}
|
||||
onSaved();
|
||||
} catch (err) {
|
||||
@@ -197,6 +218,15 @@ function EventFormModal({ event, onClose, onSaved }: {
|
||||
|
||||
return (
|
||||
<Modal title={event ? "Edit Event" : "New Event"} onClose={onClose}>
|
||||
{isAdmin && !event && (
|
||||
<FormField label="Vendor" required>
|
||||
<select style={inputStyle} value={selectedVendorId}
|
||||
onChange={(e) => setSelectedVendorId(e.target.value)} required>
|
||||
<option value="">Select vendor…</option>
|
||||
{vendors.map((v) => <option key={v.id} value={v.id}>{v.name}</option>)}
|
||||
</select>
|
||||
</FormField>
|
||||
)}
|
||||
<FormField label="Name">
|
||||
<input style={input} value={name} onChange={(e) => setName(e.target.value)} />
|
||||
</FormField>
|
||||
@@ -276,11 +306,12 @@ function EventConfigPanel({ event, onRefresh }: { event: Event; onRefresh: () =>
|
||||
const [err, setErr] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const q = `?vendorId=${encodeURIComponent(event.vendorId)}&limit=200`;
|
||||
Promise.all([
|
||||
api.get<ApiList<Tax>>("/taxes?limit=100").then((r) => setTaxes(r.data)),
|
||||
api.get<ApiList<Product>>("/products?limit=200").then((r) => setProducts(r.data)),
|
||||
api.get<ApiList<Tax>>(`/taxes${q}`).then((r) => setTaxes(r.data)),
|
||||
api.get<ApiList<Product>>(`/products${q}`).then((r) => setProducts(r.data)),
|
||||
]).catch(console.error);
|
||||
}, []);
|
||||
}, [event.vendorId]);
|
||||
|
||||
const addTax = async () => {
|
||||
setErr("");
|
||||
|
||||
Reference in New Issue
Block a user