mirror of
https://github.com/Hackdex-App/hackdex-website.git
synced 2026-09-07 08:26:07 -05:00
Fix improper caching of tags fetching
This commit is contained in:
@@ -11,10 +11,12 @@ import { updateHack, saveHackCovers, presignCoverUpload } from "@/app/hack/actio
|
||||
import SortableCovers from "@/components/Hack/SortableCovers";
|
||||
import Select from "@/components/Primitives/Select";
|
||||
import type { Database } from "@/types/db";
|
||||
import type { CatalogTagRow } from "@/types/catalogTag";
|
||||
import { FiExternalLink } from "react-icons/fi";
|
||||
|
||||
interface HackEditFormProps {
|
||||
slug: string;
|
||||
catalogTags: CatalogTagRow[];
|
||||
initial: {
|
||||
title: string;
|
||||
summary: string;
|
||||
@@ -36,7 +38,7 @@ interface HackEditFormProps {
|
||||
};
|
||||
}
|
||||
|
||||
export default function HackEditForm({ slug, initial }: HackEditFormProps) {
|
||||
export default function HackEditForm({ slug, initial, catalogTags }: HackEditFormProps) {
|
||||
const supabase = createClient();
|
||||
const MAX_COVERS = 10;
|
||||
const [title, setTitle] = React.useState(initial.title);
|
||||
@@ -363,7 +365,7 @@ export default function HackEditForm({ slug, initial }: HackEditFormProps) {
|
||||
)}
|
||||
</div>
|
||||
<div className={`rounded-md ring-1 ring-inset ${tagsChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'ring-transparent'} p-1`}>
|
||||
<TagSelector value={tags} onChange={setTags} />
|
||||
<TagSelector value={tags} onChange={setTags} catalogTags={catalogTags} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import type { CatalogTagRow } from "@/types/catalogTag";
|
||||
import HackSubmitForm from "@/components/Hack/HackSubmitForm";
|
||||
import HackEditForm from "@/components/Hack/HackEditForm";
|
||||
|
||||
@@ -12,12 +13,14 @@ interface HackFormCreateProps {
|
||||
isArchive?: boolean;
|
||||
permissionFrom?: string;
|
||||
customCreator?: string;
|
||||
catalogTags: CatalogTagRow[];
|
||||
}
|
||||
|
||||
interface HackFormEditProps {
|
||||
mode: "edit";
|
||||
slug: string;
|
||||
initial: React.ComponentProps<typeof HackEditForm>["initial"];
|
||||
catalogTags: CatalogTagRow[];
|
||||
}
|
||||
|
||||
export type HackFormProps = HackFormCreateProps | HackFormEditProps;
|
||||
@@ -29,9 +32,10 @@ export default function HackForm(props: HackFormProps) {
|
||||
isArchive={props.isArchive}
|
||||
permissionFrom={props.permissionFrom}
|
||||
customCreator={props.customCreator}
|
||||
catalogTags={props.catalogTags}
|
||||
/>;
|
||||
}
|
||||
return <HackEditForm slug={props.slug} initial={props.initial} />;
|
||||
return <HackEditForm slug={props.slug} initial={props.initial} catalogTags={props.catalogTags} />;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import BPS from "rom-patcher-js/rom-patcher-js/modules/RomPatcher.format.bps.js"
|
||||
import { sha1Hex } from "@/utils/hash";
|
||||
import { platformAccept, setDraftCovers, getDraftCovers, deleteDraftCovers } from "@/utils/idb";
|
||||
import { slugify, sortOrderedTags } from "@/utils/format";
|
||||
import type { CatalogTagRow } from "@/types/catalogTag";
|
||||
|
||||
function SortableCoverItem({ id, index, url, filename, onRemove }: { id: string; index: number; url: string; filename: string; onRemove: () => void }) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });
|
||||
@@ -66,6 +67,7 @@ interface HackSubmitFormProps {
|
||||
isArchive?: boolean;
|
||||
permissionFrom?: string;
|
||||
customCreator?: string;
|
||||
catalogTags: CatalogTagRow[];
|
||||
}
|
||||
|
||||
export default function HackSubmitForm({
|
||||
@@ -73,6 +75,7 @@ export default function HackSubmitForm({
|
||||
isArchive = false,
|
||||
permissionFrom = undefined,
|
||||
customCreator = undefined,
|
||||
catalogTags,
|
||||
}: HackSubmitFormProps) {
|
||||
const MAX_COVERS = 10;
|
||||
const { profile, user } = useAuthContext();
|
||||
@@ -899,7 +902,7 @@ export default function HackSubmitForm({
|
||||
|
||||
<div className="grid gap-2">
|
||||
<label className="text-sm text-foreground/80">Tags <span className="text-red-500">*</span></label>
|
||||
<TagSelector value={tags} onChange={setTags} />
|
||||
<TagSelector value={tags} onChange={setTags} catalogTags={catalogTags} />
|
||||
</div>
|
||||
|
||||
<div className="grid gap-1">
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import type { CatalogTagRow } from "@/types/catalogTag";
|
||||
import HackForm from "@/components/Hack/HackForm";
|
||||
import ArchiveModeSelector from "@/components/Submit/ArchiveModeSelector";
|
||||
|
||||
export default function SubmitPageClient({ canCreateArchive, dummy }: { canCreateArchive: boolean; dummy: boolean }) {
|
||||
export default function SubmitPageClient({
|
||||
canCreateArchive,
|
||||
dummy,
|
||||
catalogTags,
|
||||
}: {
|
||||
canCreateArchive: boolean;
|
||||
dummy: boolean;
|
||||
catalogTags: CatalogTagRow[];
|
||||
}) {
|
||||
const [showModeSelector, setShowModeSelector] = React.useState(canCreateArchive);
|
||||
const [customCreator, setCustomCreator] = React.useState<string | undefined>(undefined);
|
||||
const [permissionFrom, setPermissionFrom] = React.useState<string | undefined>(undefined);
|
||||
@@ -27,5 +36,6 @@ export default function SubmitPageClient({ canCreateArchive, dummy }: { canCreat
|
||||
isArchive={isArchive}
|
||||
permissionFrom={permissionFrom}
|
||||
customCreator={customCreator}
|
||||
catalogTags={catalogTags}
|
||||
/>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import type { CatalogTagRow } from "@/types/catalogTag";
|
||||
import { createClient } from "@/utils/supabase/client";
|
||||
import { MdTune } from "react-icons/md";
|
||||
import { CATEGORY_ICONS, getCategoryIcon } from "@/components/Icons/tagCategories";
|
||||
@@ -19,16 +20,13 @@ import {
|
||||
import { SortableContext, arrayMove, useSortable, rectSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { RxDragHandleDots2 } from "react-icons/rx";
|
||||
|
||||
type TagRow = {
|
||||
id: number;
|
||||
name: string;
|
||||
category: string | null;
|
||||
popularity: number;
|
||||
};
|
||||
type TagRow = CatalogTagRow;
|
||||
|
||||
export interface TagSelectorProps {
|
||||
value: string[];
|
||||
onChange: (next: string[]) => void;
|
||||
/** When set, skips client Supabase fetch (use server-cached catalog). */
|
||||
catalogTags?: CatalogTagRow[];
|
||||
}
|
||||
|
||||
type CategoryIconType = React.ComponentType<React.SVGProps<SVGSVGElement>> | null;
|
||||
@@ -114,11 +112,11 @@ function SortableSelectedTag({
|
||||
);
|
||||
}
|
||||
|
||||
export default function TagSelector({ value, onChange }: TagSelectorProps) {
|
||||
export default function TagSelector({ value, onChange, catalogTags }: TagSelectorProps) {
|
||||
const supabase = createClient();
|
||||
const [query, setQuery] = React.useState("");
|
||||
const [allTags, setAllTags] = React.useState<TagRow[]>([]);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const [allTags, setAllTags] = React.useState<TagRow[]>(() => catalogTags ?? []);
|
||||
const [loading, setLoading] = React.useState(() => catalogTags === undefined);
|
||||
const [activeCategory, _setActiveCategory] = React.useState<string | "advanced" | null>(null);
|
||||
const searchInputRef = React.useRef<HTMLInputElement | null>(null);
|
||||
const categoryRefs = React.useRef<Record<string, HTMLDivElement | null>>({});
|
||||
@@ -143,6 +141,8 @@ export default function TagSelector({ value, onChange }: TagSelectorProps) {
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (catalogTags !== undefined) return;
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@@ -156,12 +156,15 @@ export default function TagSelector({ value, onChange }: TagSelectorProps) {
|
||||
popularity: t.usage?.[0]?.count || 0,
|
||||
}));
|
||||
rows.sort((a, b) => (b.popularity - a.popularity) || a.name.localeCompare(b.name));
|
||||
setAllTags(rows);
|
||||
if (!cancelled) setAllTags(rows);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
if (!cancelled) setLoading(false);
|
||||
}
|
||||
})();
|
||||
}, [supabase]);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [catalogTags, supabase]);
|
||||
|
||||
const grouped = React.useMemo(() => {
|
||||
const map = new Map<string, TagRow[]>();
|
||||
|
||||
Reference in New Issue
Block a user