source: chapterx-frontend/src/components/story/StoryGrid.tsx@ acf690c

main
Last change on this file since acf690c was b62cefc, checked in by kikisrbinoska <srbinoskakristina07@…>, 4 months ago

Added frontend and imporoved AI Suggestions service

  • Property mode set to 100644
File size: 2.1 KB
Line 
1import React, { useState, useEffect } from 'react'
2import { Story } from '../../types'
3import { StoryCard } from '../ui/StoryCard'
4import { BookOpen } from 'lucide-react'
5
6interface StoryGridProps {
7 stories: Story[]
8 showStatus?: boolean
9 emptyMessage?: string
10 loading?: boolean
11}
12
13const SkeletonCard = () => (
14 <div className="rounded-xl overflow-hidden bg-slate-800 border border-slate-700 animate-pulse">
15 <div className="h-40 bg-slate-700" />
16 <div className="p-4 space-y-2">
17 <div className="h-4 bg-slate-700 rounded w-3/4" />
18 <div className="h-3 bg-slate-700 rounded w-1/3" />
19 <div className="h-3 bg-slate-700 rounded w-full" />
20 <div className="h-3 bg-slate-700 rounded w-5/6" />
21 <div className="flex gap-2 mt-2">
22 <div className="h-5 bg-slate-700 rounded-full w-16" />
23 <div className="h-5 bg-slate-700 rounded-full w-16" />
24 </div>
25 </div>
26 </div>
27)
28
29export const StoryGrid: React.FC<StoryGridProps> = ({
30 stories,
31 showStatus = false,
32 emptyMessage = 'No stories found.',
33 loading: externalLoading,
34}) => {
35 const [loading, setLoading] = useState(true)
36
37 useEffect(() => {
38 const timer = setTimeout(() => setLoading(false), 800)
39 return () => clearTimeout(timer)
40 }, [])
41
42 const isLoading = externalLoading !== undefined ? externalLoading : loading
43
44 if (isLoading) {
45 return (
46 <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
47 {Array.from({ length: 3 }).map((_, i) => <SkeletonCard key={i} />)}
48 </div>
49 )
50 }
51
52 if (stories.length === 0) {
53 return (
54 <div className="flex flex-col items-center justify-center py-20 text-slate-500">
55 <BookOpen size={48} className="mb-4 opacity-40" />
56 <p className="text-lg font-medium">{emptyMessage}</p>
57 <p className="text-sm mt-1">Try adjusting your search or filters.</p>
58 </div>
59 )
60 }
61
62 return (
63 <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
64 {stories.map(story => (
65 <StoryCard key={story.story_id} story={story} showStatus={showStatus} />
66 ))}
67 </div>
68 )
69}
Note: See TracBrowser for help on using the repository browser.