diff --git a/web/src/app/community/[icon]/page.tsx b/web/src/app/community/[icon]/page.tsx index 9a9a5bdf..39db50ab 100644 --- a/web/src/app/community/[icon]/page.tsx +++ b/web/src/app/community/[icon]/page.tsx @@ -5,6 +5,14 @@ import { BASE_URL, WEB_URL } from "@/constants" import { getAllIcons, getAuthorData } from "@/lib/api" import { getCommunityGalleryRecord, getCommunitySubmissionByName, getCommunitySubmissions } from "@/lib/community" +function isIconAddedToCollection( + record: Awaited>, + collectionIcons: Record, + icon: string, +) { + return record?.status === "added_to_collection" && Object.hasOwn(collectionIcons, icon) +} + export const dynamicParams = true export const revalidate = 21600 // 6 hours export const dynamic = "force-static" @@ -30,7 +38,10 @@ export async function generateMetadata({ params }: Props, _parent: ResolvingMeta } const record = await getCommunityGalleryRecord(icon) - if (record?.status === "added_to_collection") { + const collectionIcons = await getAllIcons() + const isInCollection = isIconAddedToCollection(record, collectionIcons, icon) + + if (isInCollection) { permanentRedirect(`/icons/${icon}`) } @@ -118,12 +129,12 @@ export default async function CommunityIconPage({ params }: { params: Promise<{ } const record = await getCommunityGalleryRecord(icon) - if (record?.status === "added_to_collection") { + const allIcons = await getAllIcons() + const isInCollection = isIconAddedToCollection(record, allIcons, icon) + if (isInCollection) { permanentRedirect(`/icons/${icon}`) } - const allIcons = await getAllIcons() - const author = iconData.data.update.author as any const githubId = author?.github_id const authorMetaLogin = author?.login || author?.name diff --git a/web/src/components/advanced-icon-submission-form-tanstack.tsx b/web/src/components/advanced-icon-submission-form-tanstack.tsx index a4528a61..d2add1bd 100644 --- a/web/src/components/advanced-icon-submission-form-tanstack.tsx +++ b/web/src/components/advanced-icon-submission-form-tanstack.tsx @@ -27,7 +27,6 @@ import { MultiSelect, type MultiSelectOption } from "@/components/ui/multi-selec import { Dropzone, DropzoneContent, DropzoneEmptyState } from "@/components/ui/shadcn-io/dropzone" import { Textarea } from "@/components/ui/textarea" import { REPO_PATH } from "@/constants" -import { useExistingIconNames } from "@/hooks/use-submissions" import { pb } from "@/lib/pb" interface VariantConfig { @@ -112,7 +111,6 @@ interface FormData { export function AdvancedIconSubmissionFormTanStack() { const [filePreviews, setFilePreviews] = useState>({}) const [showConfirmDialog, setShowConfirmDialog] = useState(false) - const { data: existingIcons = [] } = useExistingIconNames() const router = useRouter() const form = useForm({ @@ -383,11 +381,6 @@ export function AdvancedIconSubmissionFormTanStack() { if (!/^[a-z0-9-]+$/.test(value)) { return "Icon name must contain only lowercase letters, numbers, and hyphens" } - // Check if icon already exists - const iconExists = existingIcons.some((icon) => icon.value === value) - if (iconExists) { - return "This icon already exists. Icon updates are not yet supported. Please choose a different name." - } return undefined }, }} @@ -676,7 +669,7 @@ export function AdvancedIconSubmissionFormTanStack() { > {(state) => ( )} diff --git a/web/src/components/icon-name-combobox.tsx b/web/src/components/icon-name-combobox.tsx index 76362efe..e2df2da9 100644 --- a/web/src/components/icon-name-combobox.tsx +++ b/web/src/components/icon-name-combobox.tsx @@ -65,7 +65,7 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico // Delay to allow clicking on suggestions setTimeout(() => setIsFocused(false), 200) }} - placeholder="Type new icon ID (e.g., my-app)..." + placeholder="Type icon ID (new or existing, e.g., my-app)..." className={cn("font-mono", isInvalid && "border-destructive focus-visible:ring-destructive/50")} aria-invalid={isInvalid} aria-describedby={error ? "icon-name-error" : undefined} @@ -77,7 +77,7 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico No existing icons found - + {filteredIcons.slice(0, 50).map((icon) => ( - {icon.label} ))} @@ -109,7 +108,9 @@ export function IconNameCombobox({ value, onValueChange, error, isInvalid }: Ico {/* Helper text when no error */} {!error && value && ( -

{loading ? "Checking availability..." : "✓ Available icon ID"}

+

+ {loading ? "Loading icon names..." : "Select an existing icon to update or enter a new ID"} +

)} )