From d57c75d5d746642d5687eec6860e50bf90627b1c Mon Sep 17 00:00:00 2001 From: ct Date: Tue, 15 Jul 2025 02:38:23 +0800 Subject: [PATCH] Update --- resources/js/components/ui/grid-skeleton.jsx | 2 +- .../js/components/ui/media-item-skeleton.jsx | 7 + resources/js/components/ui/media-item.jsx | 48 +++++++ .../modules/editor/partials/edit-sidebar.jsx | 136 ++++++++++-------- 4 files changed, 135 insertions(+), 58 deletions(-) create mode 100644 resources/js/components/ui/media-item-skeleton.jsx create mode 100644 resources/js/components/ui/media-item.jsx diff --git a/resources/js/components/ui/grid-skeleton.jsx b/resources/js/components/ui/grid-skeleton.jsx index 41ff6ee..d63c782 100644 --- a/resources/js/components/ui/grid-skeleton.jsx +++ b/resources/js/components/ui/grid-skeleton.jsx @@ -5,7 +5,7 @@ const GridSkeleton = ({ itemCount = 6 }) => {
{Array.from({ length: itemCount }, (_, index) => (
-
+
))}
diff --git a/resources/js/components/ui/media-item-skeleton.jsx b/resources/js/components/ui/media-item-skeleton.jsx new file mode 100644 index 0000000..15083d4 --- /dev/null +++ b/resources/js/components/ui/media-item-skeleton.jsx @@ -0,0 +1,7 @@ +const MediaItemSkeleton = () => { + return ( +
+ ); +}; + +export { MediaItemSkeleton }; \ No newline at end of file diff --git a/resources/js/components/ui/media-item.jsx b/resources/js/components/ui/media-item.jsx new file mode 100644 index 0000000..7748d0a --- /dev/null +++ b/resources/js/components/ui/media-item.jsx @@ -0,0 +1,48 @@ +import { useState } from 'react'; +import { MediaItemSkeleton } from './media-item-skeleton'; + +const MediaItem = ({ src, alt, onClick, isSelected, className = "" }) => { + const [isLoading, setIsLoading] = useState(true); + const [hasError, setHasError] = useState(false); + + const handleImageLoad = () => { + setIsLoading(false); + }; + + const handleImageError = () => { + setIsLoading(false); + setHasError(true); + }; + + return ( +
+ {isLoading && ( +
+ +
+ )} + + {hasError ? ( +
+ Failed to load +
+ ) : ( + {alt} + )} + + {/* Selection border overlay */} + {isSelected && !isLoading && ( +
+ )} +
+ ); +}; + +export { MediaItem }; \ No newline at end of file diff --git a/resources/js/modules/editor/partials/edit-sidebar.jsx b/resources/js/modules/editor/partials/edit-sidebar.jsx index e421d3d..15034e9 100644 --- a/resources/js/modules/editor/partials/edit-sidebar.jsx +++ b/resources/js/modules/editor/partials/edit-sidebar.jsx @@ -1,6 +1,7 @@ import { Button } from '@/components/ui/button'; import { GridSkeleton } from '@/components/ui/grid-skeleton'; import { Input } from '@/components/ui/input'; +import { MediaItem } from '@/components/ui/media-item'; import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { cn } from '@/lib/utils'; @@ -28,17 +29,17 @@ export default function EditSidebar({ isOpen, onClose }) { // Track the current active tab const [activeTab, setActiveTab] = useState('memes'); - + // Track search queries const [searchQueries, setSearchQueries] = useState({ memes: '', - backgrounds: '' + backgrounds: '', }); - + // Track if data has been loaded for each tab (to prevent infinite loading on empty results) const [dataLoaded, setDataLoaded] = useState({ memes: false, - backgrounds: false + backgrounds: false, }); // Fetch data when sidebar opens for the current active tab @@ -48,22 +49,22 @@ export default function EditSidebar({ isOpen, onClose }) { const query = searchQueries.memes; if (query) { searchMemes(query).finally(() => { - setDataLoaded(prev => ({ ...prev, memes: true })); + setDataLoaded((prev) => ({ ...prev, memes: true })); }); } else { fetchMemes().finally(() => { - setDataLoaded(prev => ({ ...prev, memes: true })); + setDataLoaded((prev) => ({ ...prev, memes: true })); }); } } else if (activeTab === 'backgrounds' && !dataLoaded.backgrounds && !isFetchingBackgrounds) { const query = searchQueries.backgrounds; if (query) { searchBackgrounds(query).finally(() => { - setDataLoaded(prev => ({ ...prev, backgrounds: true })); + setDataLoaded((prev) => ({ ...prev, backgrounds: true })); }); } else { fetchBackgrounds().finally(() => { - setDataLoaded(prev => ({ ...prev, backgrounds: true })); + setDataLoaded((prev) => ({ ...prev, backgrounds: true })); }); } } @@ -76,22 +77,22 @@ export default function EditSidebar({ isOpen, onClose }) { const query = searchQueries.memes; if (query) { searchMemes(query).finally(() => { - setDataLoaded(prev => ({ ...prev, memes: true })); + setDataLoaded((prev) => ({ ...prev, memes: true })); }); } else { fetchMemes().finally(() => { - setDataLoaded(prev => ({ ...prev, memes: true })); + setDataLoaded((prev) => ({ ...prev, memes: true })); }); } } else if (value === 'backgrounds' && !dataLoaded.backgrounds && !isFetchingBackgrounds) { const query = searchQueries.backgrounds; if (query) { searchBackgrounds(query).finally(() => { - setDataLoaded(prev => ({ ...prev, backgrounds: true })); + setDataLoaded((prev) => ({ ...prev, backgrounds: true })); }); } else { fetchBackgrounds().finally(() => { - setDataLoaded(prev => ({ ...prev, backgrounds: true })); + setDataLoaded((prev) => ({ ...prev, backgrounds: true })); }); } } @@ -99,9 +100,9 @@ export default function EditSidebar({ isOpen, onClose }) { // Handle search input changes const handleSearchChange = (value) => { - setSearchQueries(prev => ({ + setSearchQueries((prev) => ({ ...prev, - [activeTab]: value + [activeTab]: value, })); }; @@ -110,30 +111,30 @@ export default function EditSidebar({ isOpen, onClose }) { const query = searchQueries[activeTab]; if (activeTab === 'memes') { searchMemes(query).finally(() => { - setDataLoaded(prev => ({ ...prev, memes: true })); + setDataLoaded((prev) => ({ ...prev, memes: true })); }); } else if (activeTab === 'backgrounds') { searchBackgrounds(query).finally(() => { - setDataLoaded(prev => ({ ...prev, backgrounds: true })); + setDataLoaded((prev) => ({ ...prev, backgrounds: true })); }); } }; // Handle clearing search const handleClearSearch = () => { - setSearchQueries(prev => ({ + setSearchQueries((prev) => ({ ...prev, - [activeTab]: '' + [activeTab]: '', })); - + // Reset data loaded state and fetch fresh data without search if (activeTab === 'memes') { fetchMemes().finally(() => { - setDataLoaded(prev => ({ ...prev, memes: true })); + setDataLoaded((prev) => ({ ...prev, memes: true })); }); } else if (activeTab === 'backgrounds') { fetchBackgrounds().finally(() => { - setDataLoaded(prev => ({ ...prev, backgrounds: true })); + setDataLoaded((prev) => ({ ...prev, backgrounds: true })); }); } }; @@ -178,7 +179,7 @@ export default function EditSidebar({ isOpen, onClose }) { Selected Meme
) : ( -
+
No meme
)} @@ -197,7 +198,7 @@ export default function EditSidebar({ isOpen, onClose }) { Selected Background
) : ( -
+
No background
)} @@ -216,56 +217,61 @@ export default function EditSidebar({ isOpen, onClose }) { {/* Search Bar */}
- + handleSearchChange(e.target.value)} onKeyDown={handleSearchKeyDown} - className="pl-10 pr-10" + className="pr-10 pl-10" /> {searchQueries[activeTab] && ( )}
-
{isFetchingBackgrounds && } - {!isFetchingBackgrounds && backgrounds.length === 0 &&
No backgrounds found.
} + {!isFetchingBackgrounds && backgrounds.length === 0 && ( +
+

No backgrounds found.

+
+ {searchQueries.backgrounds && ( + + )} + {import.meta.env.VITE_DISCORD_LINK && ( + + )} +
+
+ )} {!isFetchingBackgrounds && backgrounds.length > 0 && ( <> -
+
{backgrounds.map((item, index) => ( - + isSelected={selectedBackground?.ids === item.ids} + className="transition-all hover:ring-2 hover:ring-blue-500" + /> ))}
@@ -274,21 +280,37 @@ export default function EditSidebar({ isOpen, onClose }) { {isFetchingMemes && } - {!isFetchingMemes && memes.length === 0 &&
No memes found.
} + {!isFetchingMemes && memes.length === 0 && ( +
+

No memes found.

+
+ {searchQueries.memes && ( + + )} + {import.meta.env.VITE_DISCORD_LINK && ( + + )} +
+
+ )} {!isFetchingMemes && memes.length > 0 && ( <>
{memes.map((item, index) => ( - + isSelected={selectedMeme?.ids === item.ids} + className="transition-all hover:ring-2 hover:ring-blue-500" + /> ))}