diff --git a/packages/ui/src/App.tsx b/packages/ui/src/App.tsx index 3a90aba4..9bba293c 100644 --- a/packages/ui/src/App.tsx +++ b/packages/ui/src/App.tsx @@ -82,6 +82,7 @@ const AppWrapper = () => { } /> } /> } /> + } /> } /> } /> } /> @@ -114,6 +115,7 @@ const AppWrapper = () => { } /> } /> } /> + } /> } /> } /> } /> diff --git a/packages/ui/src/components/GalleryLarge.tsx b/packages/ui/src/components/GalleryLarge.tsx index 8c147596..ef8fd2bf 100644 --- a/packages/ui/src/components/GalleryLarge.tsx +++ b/packages/ui/src/components/GalleryLarge.tsx @@ -1,16 +1,13 @@ -import { MediaGrid, PhotoGrid } from "./PhotoGrid"; import MediaCard from "./MediaCard"; import React, { useEffect, useState, useRef } from "react"; import { useAuth } from "@/hooks/useAuth"; import { useNavigate } from "react-router-dom"; -import { useProfiles } from "@/contexts/ProfilesContext"; import { usePostNavigation } from "@/hooks/usePostNavigation"; import { useOrganization } from "@/contexts/OrganizationContext"; import { useFeedData } from "@/hooks/useFeedData"; import { normalizeMediaType, isVideoType } from "@/lib/mediaRegistry"; -import { UserProfile } from '../pages/Post/types'; import * as db from '../pages/Post/db'; -import type { MediaItem, MediaType } from "@/types"; +import type { MediaItem } from "@/types"; import { supabase } from "@/integrations/supabase/client"; // Duplicate types for now or we could reuse specific generic props @@ -24,6 +21,7 @@ interface GalleryLargeProps { navigationSource?: 'home' | 'collection' | 'tag' | 'user'; navigationSourceId?: string; sortBy?: FeedSortOption; + categorySlugs?: string[]; } const GalleryLarge = ({ @@ -31,7 +29,8 @@ const GalleryLarge = ({ customLoading, navigationSource = 'home', navigationSourceId, - sortBy = 'latest' + sortBy = 'latest', + categorySlugs }: GalleryLargeProps) => { const { user } = useAuth(); const navigate = useNavigate(); @@ -48,6 +47,7 @@ const GalleryLarge = ({ isOrgContext, orgSlug, sortBy, + categorySlugs, // Disable hook if we have custom pictures enabled: !customPictures }); diff --git a/packages/ui/src/components/ListLayout.tsx b/packages/ui/src/components/ListLayout.tsx index 9561ed66..6ce9369b 100644 --- a/packages/ui/src/components/ListLayout.tsx +++ b/packages/ui/src/components/ListLayout.tsx @@ -17,6 +17,7 @@ interface ListLayoutProps { navigationSource?: 'home' | 'collection' | 'tag' | 'user'; navigationSourceId?: string; isOwner?: boolean; // Not strictly used for rendering list but good for consistency + categorySlugs?: string[]; } const ListItem = ({ item, isSelected, onClick }: { item: any, isSelected: boolean, onClick: () => void }) => { @@ -95,7 +96,8 @@ const ListItem = ({ item, isSelected, onClick }: { item: any, isSelected: boolea export const ListLayout = ({ sortBy = 'latest', navigationSource = 'home', - navigationSourceId + navigationSourceId, + categorySlugs }: ListLayoutProps) => { const navigate = useNavigate(); const isMobile = useIsMobile(); @@ -114,7 +116,8 @@ export const ListLayout = ({ sourceId: navigationSourceId, isOrgContext, orgSlug, - sortBy + sortBy, + categorySlugs }); // console.log('posts', feedPosts); diff --git a/packages/ui/src/components/PageActions.tsx b/packages/ui/src/components/PageActions.tsx index db30d8c2..6cee4793 100644 --- a/packages/ui/src/components/PageActions.tsx +++ b/packages/ui/src/components/PageActions.tsx @@ -36,6 +36,7 @@ interface PageActionsProps { onToggleEditMode?: () => void; onPageUpdate: (updatedPage: Page) => void; onDelete?: () => void; + onMetaUpdated?: () => void; className?: string; showLabels?: boolean; } @@ -47,6 +48,7 @@ export const PageActions = ({ onToggleEditMode, onPageUpdate, onDelete, + onMetaUpdated, className, showLabels = true }: PageActionsProps) => { @@ -109,18 +111,24 @@ export const PageActions = ({ } }; - const handleMetaUpdate = (newMeta: any) => { - // PageActions locally updates the page object. - // Ideally we should reload the page via UserPage but this gives instant feedback. + const handleMetaUpdate = async (newMeta: any) => { + // Update local state immediately for responsive UI onPageUpdate({ ...page, meta: newMeta }); - // NOTE: If meta update persists to DB elsewhere (CategoryManager), it should probably handle invalidation too. - // But if CategoryManager is purely local until save, then we do nothing. - // Looking at CategoryManager usage, it likely saves. - // We might want to pass invalidatePageCache to it or call it here if we know it saved. - // Use timeout to debounce invalidation? For now assume CategoryManager handles its own saving/invalidation or we rely on page refresh. - // Actually, CategoryManager props has "onPageMetaUpdate", which updates local state. - // If CategoryManager saves to DB, it should invalidate. - // Let's stick to the handlers we control here. + + // Persist to database + try { + const { updatePageMeta } = await import('@/lib/db'); + await updatePageMeta(page.id, newMeta); + invalidatePageCache(); + + // Trigger parent refresh to get updated category_paths + if (onMetaUpdated) { + onMetaUpdated(); + } + } catch (error) { + console.error('Failed to update page meta:', error); + toast.error(translate('Failed to update categories')); + } }; const handleToggleVisibility = async (e?: React.MouseEvent) => { @@ -516,6 +524,8 @@ draft: ${!page.visible} currentPageId={page.id} currentPageMeta={page.meta} onPageMetaUpdate={handleMetaUpdate} + filterByType="pages" + defaultMetaType="pages" /> {/* Legacy/Standard Parent Picker - Keeping relevant as "Page Hierarchy" vs "Category Taxonomy" */} diff --git a/packages/ui/src/components/PageCard.tsx b/packages/ui/src/components/PageCard.tsx index 86318900..88c093bf 100644 --- a/packages/ui/src/components/PageCard.tsx +++ b/packages/ui/src/components/PageCard.tsx @@ -11,6 +11,8 @@ interface PageCardProps extends Omit { variant?: 'grid' | 'feed'; responsive?: any; showContent?: boolean; + showHeader?: boolean; + overlayMode?: 'hover' | 'always'; authorAvatarUrl?: string | null; created_at?: string; apiUrl?: string; @@ -35,6 +37,8 @@ const PageCard: React.FC = ({ variant = 'grid', responsive, showContent = true, + showHeader = true, + overlayMode = 'hover', apiUrl, versionCount }) => { @@ -69,16 +73,18 @@ const PageCard: React.FC = ({ className="group relative overflow-hidden bg-card transition-all duration-300 cursor-pointer w-full border rounded-lg mb-4" onClick={handleCardClick} > -
- -
+ {showHeader && ( +
+ +
+ )}
{isPlaying && isExternalVideo ? ( @@ -126,28 +132,30 @@ const PageCard: React.FC = ({ )}
-
-
-

{title}

-
- - {description && ( -
- + {showContent && ( +
+
+

{title}

- )} -
- - + {description && ( +
+ +
+ )} + +
+ + +
-
+ )}
); } @@ -208,7 +216,7 @@ const PageCard: React.FC = ({ )} {showContent && ( -
+