fix: resolve CI and workspace lint errors (admin + storefront)
Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m11s

- Allow require() in next.config.js (eslint-disable) for both apps
- Replace all catch (e: any) with catch (e: unknown) and proper error handling
- Remove no-explicit-any: add types (PreviewProduct, ProductImage, Id<addresses>,
  ProductDetailReview, error payloads) across admin and storefront
- Admin: use next/image in ImageUploadSection and ProductImageCarousel; remove
  unused layout fonts and sidebar imports; fix products page useMemo deps
- Storefront: use Link for /sign-in in header actions; fix useAddressMutations
  and product detail types; remove unused imports/vars and fix useMemo deps

Made-with: Cursor
This commit is contained in:
2026-03-08 00:45:57 +03:00
parent 2f5537cf7e
commit 23efcab80c
34 changed files with 87 additions and 89 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { Button, Chip, RadioGroup, Radio, Label, Skeleton } from "@heroui/react";
import { Button, Chip, RadioGroup, Radio, Skeleton } from "@heroui/react";
import type { CheckoutAddress } from "@/lib/checkout/types";
type AddressSelectorProps = {

View File

@@ -1,5 +1,6 @@
"use client";
import Link from "next/link";
import { useConvexAuth } from "convex/react";
import { UserButton } from "@clerk/nextjs";
@@ -27,7 +28,7 @@ export function HeaderUserAction() {
if (isLoading || !isAuthenticated) {
return (
<a
<Link
href="/sign-in"
className="group flex flex-col items-center gap-1"
>
@@ -48,7 +49,7 @@ export function HeaderUserAction() {
<span className="text-[10px] font-medium tracking-wide text-[#3d5554] transition-colors group-hover:text-[#236f6b]">
Sign In
</span>
</a>
</Link>
);
}

View File

@@ -1,5 +1,6 @@
"use client";
import Link from "next/link";
import { useConvexAuth } from "convex/react";
import { UserButton } from "@clerk/nextjs";
@@ -27,7 +28,7 @@ export function MobileHeaderUserAction() {
if (isLoading || !isAuthenticated) {
return (
<a
<Link
href="/sign-in"
className="flex h-8 w-8 items-center justify-center rounded-full border border-[#d9e8e7] bg-[#f9fcfb]"
>
@@ -45,7 +46,7 @@ export function MobileHeaderUserAction() {
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
<circle cx="12" cy="7" r="4" />
</svg>
</a>
</Link>
);
}

View File

@@ -4,7 +4,7 @@ import { useState } from "react";
import { useQuery } from "convex/react";
import { api } from "../../../../../../convex/_generated/api";
import type { Id } from "../../../../../../convex/_generated/dataModel";
import { ReviewSortOption } from "@/lib/product-detail/types";
import type { ProductDetailReview, ReviewSortOption } from "@/lib/product-detail/types";
import { ReviewSortBar } from "./ReviewSortBar";
import { ReviewList } from "./ReviewList";
import { ReviewForm } from "./ReviewForm";
@@ -58,7 +58,7 @@ export function ProductDetailReviewsPanel({ productId, initialRating, initialRev
onSortChange={handleSortChange}
/>
<ReviewList
reviews={page as any}
reviews={page as ProductDetailReview[]}
total={total}
hasMore={hasMore}
isLoading={result === undefined}

View File

@@ -206,7 +206,10 @@ export function ProductDetailHeroSection({
const [addError, setAddError] = useState<string | null>(null);
const images: ProductDetailImage[] = product.images ?? [];
const variants: ProductDetailVariant[] = product.variants ?? [];
const variants = useMemo(
() => (product.variants ?? []) as ProductDetailVariant[],
[product.variants],
);
const mainImage = images[selectedImageIndex] ?? images[0];
const dimensions = useMemo(
() => getAttributeDimensions(variants),

View File

@@ -23,7 +23,7 @@ export async function ProductDetailHeroSectionWrapper({
return (
<ProductDetailHeroSection
product={product as any}
product={product}
category={category}
subCategory={subCategory}
/>

View File

@@ -1,4 +1,3 @@
import { Suspense } from "react";
import { fetchQuery } from "convex/nextjs";
import { notFound } from "next/navigation";
import { api } from "../../../../../../convex/_generated/api";

View File

@@ -22,16 +22,6 @@ type ShopFilterContentProps = {
isLoading?: boolean;
};
const FILTER_SECTION_IDS = [
"brand",
"tags",
"petSize",
"ageRange",
"specialDiet",
"material",
"flavor",
] as const;
export function ShopFilterContent({
options,
value,

View File

@@ -9,7 +9,6 @@ import type { ShopFilterState } from "@/lib/shop/filterState";
* otherwise renders children (e.g. sub-category links).
*/
export function ShopFilterSidebar({
children,
className,
filterOptions,
filterState,

View File

@@ -10,7 +10,6 @@ export function ShopToolbar({
currentSort,
onSortChange,
onOpenFilter,
resultCount,
}: {
sortOptions: SortOption[];
currentSort: string;

View File

@@ -15,8 +15,7 @@ import { WishlistSignInPrompt } from "./state/WishlistSignInPrompt";
export function WishlistPageView() {
const { isAuthenticated, isLoading: authLoading } = useConvexAuth();
const { items, isLoading, isEmpty } = useWishlist();
const { removeItem, isRemoving, addToCart, isAddingToCart } =
useWishlistMutations();
const { removeItem, isRemoving, addToCart } = useWishlistMutations();
const [removeTarget, setRemoveTarget] = useState<WishlistItem | null>(null);
const [removingId, setRemovingId] = useState<string | null>(null);

View File

@@ -1,7 +1,6 @@
"use client";
import Link from "next/link";
import { WISHLIST_PATH } from "@/lib/wishlist/constants";
function HeartIcon() {
return (