Payments minor navigation and UI bugs fixed (#1585)

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/hexclave/hexclave/blob/dev/CONTRIBUTING.md

-->


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes product creation navigation and the quantity selector layout in
Payments. Links now resolve to the correct project route and the
quantity control no longer squishes or wraps.

- **Bug Fixes**
- Use admin app `projectId` and a shared `getCreateProductHref` helper
to build product creation URLs, preserving `productLineId` and
`customerType` when present.
- Prevent quantity selector buttons from shrinking and wrap the input in
a fixed-width container to keep the control stable in tight layouts.

<sup>Written for commit 22d2eb6d90.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1585?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Armaan Jain 2026-06-11 11:38:00 -07:00 committed by GitHub
parent 74c888fed7
commit a092be6dc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 17 deletions

View File

@ -1155,7 +1155,8 @@ function productLineTypeKeyToString(key: ProductLineTypeKey): string {
}
function ProductLineView({ groupedProducts, groups, existingItems, onSaveProduct, onDeleteProduct, onCreateNewItem, onOpenProductDetails, onSaveProductWithGroup, onCreateProductLine, onUpdateProductLine, onDeleteProductLine, createDraftRequestId, draftCustomerType, onDraftHandled, paymentsConfig, onMoveProduct }: ProductLineViewProps) {
const projectId = useProjectId();
const hexclaveAdminApp = useAdminApp();
const projectId = hexclaveAdminApp.projectId;
const [drafts, setDrafts] = useState<Array<{ key: string, productLineId: string | undefined, product: Product }>>([]);
const [creatingGroupKey, setCreatingGroupKey] = useState<string | undefined>(undefined);
const [newProductLineDisplayName, setNewProductLineDisplayName] = useState("");
@ -1203,6 +1204,12 @@ function ProductLineView({ groupedProducts, groups, existingItems, onSaveProduct
return new Set(all);
}, [groupedProducts, drafts]);
const lastHandledDraftRequestRef = useRef<string | undefined>(undefined);
const getCreateProductHref = (productLineId: string | undefined, customerType: 'user' | 'team' | 'custom' | undefined) => {
if (productLineId == null || customerType == null) {
return urlString`/projects/${projectId}/payments/products/new`;
}
return urlString`/projects/${projectId}/payments/products/new?productLineId=${productLineId}&customerType=${customerType}`;
};
useEffect(() => {
if (!createDraftRequestId) return;
@ -1478,7 +1485,7 @@ function ProductLineView({ groupedProducts, groups, existingItems, onSaveProduct
))}
{/* Add product button */}
<Link href={productLineId && customerType ? urlString`/projects/${projectId}/payments/products/new?productLineId=${productLineId}&customerType=${customerType}` : urlString`/projects/${projectId}/payments/products/new`}>
<Link href={getCreateProductHref(productLineId, customerType)}>
<Button
variant="outline"
size="plain"
@ -1533,7 +1540,7 @@ function ProductLineView({ groupedProducts, groups, existingItems, onSaveProduct
onOpenDetails={(o) => onOpenProductDetails(o)}
/>
))}
<Link href={`/projects/${projectId}/payments/products/new`}>
<Link href={getCreateProductHref(undefined, undefined)}>
<Button
variant="outline"
size="plain"

View File

@ -45,30 +45,32 @@ export function PurchaseQuantitySelector({
type="button"
size="icon"
variant="outline"
className="size-8 border-border/40 bg-foreground/[0.01] hover:bg-foreground/[0.03]"
className="size-8 shrink-0 border-border/40 bg-foreground/[0.01] hover:bg-foreground/[0.03]"
disabled={quantityNumber <= 1}
aria-label="Decrease quantity"
onClick={() => onQuantityChange(String(Math.max(1, quantityNumber - 1)))}
>
<MinusIcon className="size-3.5 text-foreground" />
</DesignButton>
<DesignInput
className="h-8 w-20 text-center text-sm font-semibold tabular-nums border-border/40 bg-foreground/[0.01] text-foreground focus-visible:ring-blue-500/20"
inputMode="numeric"
pattern="[0-9]*"
type="text"
value={quantityInput}
aria-label="Quantity"
onChange={(event) => {
const digitsOnly = event.target.value.replace(/[^0-9]/g, "");
onQuantityChange(digitsOnly);
}}
/>
<div className="w-20 shrink-0">
<DesignInput
className="h-8 text-center text-sm font-semibold tabular-nums border-border/40 bg-foreground/[0.01] text-foreground focus-visible:ring-blue-500/20"
inputMode="numeric"
pattern="[0-9]*"
type="text"
value={quantityInput}
aria-label="Quantity"
onChange={(event) => {
const digitsOnly = event.target.value.replace(/[^0-9]/g, "");
onQuantityChange(digitsOnly);
}}
/>
</div>
<DesignButton
type="button"
size="icon"
variant="outline"
className="size-8 border-border/40 bg-foreground/[0.01] hover:bg-foreground/[0.03]"
className="size-8 shrink-0 border-border/40 bg-foreground/[0.01] hover:bg-foreground/[0.03]"
aria-label="Increase quantity"
onClick={() => onQuantityChange(String(quantityNumber + 1))}
>