refactor(inventory): site selector via URL param (?siteId=) — no localStorage, no user preference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4919b1d4e4
commit
e887502e27
2 changed files with 27 additions and 24 deletions
|
|
@ -1,10 +1,10 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useMemo, useTransition } from "react";
|
import { useState, useMemo } from "react";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import { Search, X, ChevronDown, ChevronRight, MapPin, Tag } from "lucide-react";
|
import { Search, X, ChevronDown, ChevronRight, MapPin, Tag } from "lucide-react";
|
||||||
import { formatCurrency } from "@/lib/utils";
|
import { formatCurrency } from "@/lib/utils";
|
||||||
import { addToCart } from "@/lib/cart";
|
import { addToCart } from "@/lib/cart";
|
||||||
import { setPreferredSite } from "@/app/actions/site-preference";
|
|
||||||
|
|
||||||
type VendorOption = {
|
type VendorOption = {
|
||||||
vendorId: string;
|
vendorId: string;
|
||||||
|
|
@ -32,18 +32,18 @@ export function ItemsTable({
|
||||||
items,
|
items,
|
||||||
hasSite,
|
hasSite,
|
||||||
sites = [],
|
sites = [],
|
||||||
preferredSiteId = null,
|
currentSiteId = null,
|
||||||
}: {
|
}: {
|
||||||
items: CatalogItem[];
|
items: CatalogItem[];
|
||||||
hasSite: boolean;
|
hasSite: boolean;
|
||||||
sites?: SiteOption[];
|
sites?: SiteOption[];
|
||||||
preferredSiteId?: string | null;
|
currentSiteId?: string | null;
|
||||||
}) {
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const [expandedId, setExpandedId] = useState<string | null>(null);
|
const [expandedId, setExpandedId] = useState<string | null>(null);
|
||||||
const [sortBy, setSortBy] = useState<"distance" | "price">(hasSite ? "distance" : "price");
|
const [sortBy, setSortBy] = useState<"distance" | "price">(hasSite ? "distance" : "price");
|
||||||
const [added, setAdded] = useState<Record<string, boolean>>({});
|
const [added, setAdded] = useState<Record<string, boolean>>({});
|
||||||
const [sitePending, startSiteTransition] = useTransition();
|
|
||||||
|
|
||||||
const filtered = useMemo(() => {
|
const filtered = useMemo(() => {
|
||||||
const q = query.toLowerCase().trim();
|
const q = query.toLowerCase().trim();
|
||||||
|
|
@ -99,20 +99,19 @@ export function ItemsTable({
|
||||||
<MapPin className="h-4 w-4 text-neutral-400 shrink-0" />
|
<MapPin className="h-4 w-4 text-neutral-400 shrink-0" />
|
||||||
<label className="text-sm font-medium text-neutral-700 whitespace-nowrap">Working Site</label>
|
<label className="text-sm font-medium text-neutral-700 whitespace-nowrap">Working Site</label>
|
||||||
<select
|
<select
|
||||||
value={preferredSiteId ?? ""}
|
value={currentSiteId ?? ""}
|
||||||
disabled={sitePending}
|
onChange={(e) => {
|
||||||
onChange={(e) =>
|
const id = e.target.value;
|
||||||
startSiteTransition(() => setPreferredSite(e.target.value || null))
|
router.push(id ? `/inventory/items?siteId=${id}` : "/inventory/items");
|
||||||
}
|
}}
|
||||||
className="flex-1 max-w-xs rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-1.5 text-sm text-neutral-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20 disabled:opacity-60"
|
className="flex-1 max-w-xs rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-1.5 text-sm text-neutral-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"
|
||||||
>
|
>
|
||||||
<option value="">No site selected — distances hidden</option>
|
<option value="">No site selected — distances hidden</option>
|
||||||
{sites.map((s) => (
|
{sites.map((s) => (
|
||||||
<option key={s.id} value={s.id}>{s.name} ({s.code})</option>
|
<option key={s.id} value={s.id}>{s.name} ({s.code})</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{sitePending && <span className="text-xs text-neutral-400">Updating…</span>}
|
{currentSiteId && (
|
||||||
{!sitePending && preferredSiteId && (
|
|
||||||
<span className="text-xs text-primary-600">Distances shown from selected site</span>
|
<span className="text-xs text-primary-600">Distances shown from selected site</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,23 @@ import type { Metadata } from "next";
|
||||||
|
|
||||||
export const metadata: Metadata = { title: "Browse Items" };
|
export const metadata: Metadata = { title: "Browse Items" };
|
||||||
|
|
||||||
export default async function InventoryItemsPage() {
|
interface Props {
|
||||||
|
searchParams: Promise<{ siteId?: string }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function InventoryItemsPage({ searchParams }: Props) {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session?.user) redirect("/login");
|
if (!session?.user) redirect("/login");
|
||||||
|
|
||||||
const [user, products, sites] = await Promise.all([
|
const { siteId } = await searchParams;
|
||||||
db.user.findUnique({
|
|
||||||
where: { id: session.user.id },
|
const [site, products, sites] = await Promise.all([
|
||||||
include: {
|
siteId
|
||||||
preferredSite: { select: { id: true, name: true, latitude: true, longitude: true } },
|
? db.site.findUnique({
|
||||||
},
|
where: { id: siteId, isActive: true },
|
||||||
}),
|
select: { id: true, name: true, latitude: true, longitude: true },
|
||||||
|
})
|
||||||
|
: Promise.resolve(null),
|
||||||
db.product.findMany({
|
db.product.findMany({
|
||||||
where: { isActive: true },
|
where: { isActive: true },
|
||||||
include: {
|
include: {
|
||||||
|
|
@ -40,8 +46,6 @@ export default async function InventoryItemsPage() {
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const site = user?.preferredSite ?? null;
|
|
||||||
|
|
||||||
const items = products.map((p) => ({
|
const items = products.map((p) => ({
|
||||||
id: p.id,
|
id: p.id,
|
||||||
code: p.code,
|
code: p.code,
|
||||||
|
|
@ -72,7 +76,7 @@ export default async function InventoryItemsPage() {
|
||||||
items={items}
|
items={items}
|
||||||
hasSite={!!site}
|
hasSite={!!site}
|
||||||
sites={sites}
|
sites={sites}
|
||||||
preferredSiteId={user?.preferredSiteId ?? null}
|
currentSiteId={siteId ?? null}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue