diff --git a/src/app/PageClient.tsx b/src/app/PageClient.tsx index defc132..e360685 100644 --- a/src/app/PageClient.tsx +++ b/src/app/PageClient.tsx @@ -36,6 +36,8 @@ interface PageClientProps { settings?: Partial | null testimonials?: Testimonial[] posts?: BlogPost[] + instagramAccount?: any | null + instagramMedia?: any[] isAdminPreview?: boolean } @@ -45,6 +47,8 @@ export default function PageClient({ settings: settingsInput, testimonials = [], posts = [], + instagramAccount = null, + instagramMedia = [], isAdminPreview = false, }: PageClientProps) { const settings = mergeSiteSettings(settingsInput) @@ -145,7 +149,7 @@ export default function PageClient({ > - + {settings.show_testimonials ? ( diff --git a/src/app/page.tsx b/src/app/page.tsx index c5b772f..dd1fbbf 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,6 +10,8 @@ export default async function Home() { let technologies: any[] = []; let testimonials: any[] = []; let posts: any[] = []; + let instagramAccount: any = null; + let instagramMedia: any[] = []; let settings: any = defaultSiteSettings; let isAdmin = false; @@ -18,18 +20,22 @@ export default async function Home() { const { data: { user } } = await supabase.auth.getUser(); isAdmin = isAdminUser(user); - const [projectsRes, techRes, settingsRes, testimonialsRes, postsRes] = await Promise.all([ + const [projectsRes, techRes, settingsRes, testimonialsRes, postsRes, instagramAccountRes, instagramMediaRes] = await Promise.all([ supabase.from('projects').select('*, technologies(*)').order('is_featured', { ascending: false }).order('featured_order').order('created_at', { ascending: false }), supabase.from('technologies').select('*'), supabase.from('site_settings').select('*').eq('id', 1).maybeSingle(), supabase.from('testimonials').select('*').eq('approved', true).order('display_order').limit(6), supabase.from('posts').select('*').eq('published', true).order('published_at', { ascending: false }).limit(3), + supabase.from('instagram_accounts').select('username,name,biography,website,profile_picture_url,followers_count,follows_count,media_count').eq('is_active', true).order('updated_at', { ascending: false }).limit(1).maybeSingle(), + supabase.from('instagram_media').select('id,media_type,media_product_type,media_url,thumbnail_url,permalink,caption,like_count,comments_count,posted_at').eq('is_visible', true).order('posted_at', { ascending: false }).limit(24), ]); projects = projectsRes.data || []; technologies = techRes.data || []; settings = settingsRes.data || defaultSiteSettings; testimonials = testimonialsRes.data || []; posts = postsRes.data || []; + instagramAccount = instagramAccountRes.data || null; + instagramMedia = instagramMediaRes.data || []; } catch (err) { console.error('Failed to load portfolio data:', err); } @@ -56,6 +62,8 @@ export default async function Home() { settings={settings} testimonials={testimonials} posts={posts} + instagramAccount={instagramAccount} + instagramMedia={instagramMedia} isAdminPreview={settings.maintenance_mode && isAdmin} /> ); diff --git a/src/components/sections/InstagramPostGallery.tsx b/src/components/sections/InstagramPostGallery.tsx index d820451..9ca56d3 100644 --- a/src/components/sections/InstagramPostGallery.tsx +++ b/src/components/sections/InstagramPostGallery.tsx @@ -31,6 +31,35 @@ interface LiveInstagramAccount { media_count: number } +interface LiveInstagramMedia { + id: string + media_type: string + media_product_type: string + media_url: string | null + thumbnail_url: string | null + permalink: string + caption: string | null + like_count: number + comments_count: number + posted_at?: string | null +} + +interface InstagramPostGalleryProps { + initialAccount?: LiveInstagramAccount | null + initialMedia?: LiveInstagramMedia[] +} + +const mapLiveMedia = (items: LiveInstagramMedia[]): GridPost[] => items.map((item) => ({ + id: item.id, + image: item.thumbnail_url || item.media_url || '/hero-cyber-portrait.jpg', + postUrl: item.permalink, + isReel: item.media_product_type === 'REELS', + isCarousel: item.media_type === 'CAROUSEL_ALBUM', + likes: String(item.like_count || 0), + comments: String(item.comments_count || 0), + caption: item.caption || 'Instagram media', +})) + const PROFILE_PIC = "https://scontent.cdninstagram.com/v/t51.82787-19/683766249_18314607391302713_2744361709957459017_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=102&ccb=7-5&_nc_sid=f7ccc5&efg=eyJ2ZW5jb2RlX3RhZyI6InByb2ZpbGVfcGljLnd3dy4xMDgwLkMzIn0%3D&_nc_ohc=Sz5jW7y0jYwQ7kNvwEbTgId&_nc_oc=Adpf7AFfRTY1ZduD488bEFs_RaUxtREJuuZxQiTcQb5KgQdULpoUNqAZBDNNjOLu8Ig&_nc_zt=24&_nc_ht=scontent.cdninstagram.com&_nc_gid=BVxtCcXPgZ5lz3sdw1fR4w&_nc_ss=7b6a8&oh=00_AQEc9LGAmKVEjRI9A7x_u2cjSuYkS-Zj7j4YXS9xCVZ-QA&oe=6A72EAD9" const INSTAGRAM_GRID: GridPost[] = [ @@ -160,10 +189,10 @@ const HIGHLIGHTS = [ { name: 'Cyber', label: '🔥', color: 'bg-cyan-950 text-cyan-400 border-cyan-500/40' }, ] -export default function InstagramPostGallery() { +export default function InstagramPostGallery({ initialAccount = null, initialMedia = [] }: InstagramPostGalleryProps) { const [activeTab, setActiveTab] = useState<'posts' | 'reels' | 'saved'>('posts') - const [livePosts, setLivePosts] = useState([]) - const [liveAccount, setLiveAccount] = useState(null) + const [livePosts, setLivePosts] = useState(() => mapLiveMedia(initialMedia)) + const [liveAccount, setLiveAccount] = useState(initialAccount) const { playClick, playHover } = useAudio() const profileUrl = `https://www.instagram.com/${liveAccount?.username || 'sahad_____sha'}/` @@ -176,24 +205,13 @@ export default function InstagramPostGallery() { ]) if (!active) return if (account) setLiveAccount(account as LiveInstagramAccount) - if (media?.length) { - setLivePosts(media.map((item: any) => ({ - id: item.id, - image: item.thumbnail_url || item.media_url || '/hero-cyber-portrait.jpg', - postUrl: item.permalink, - isReel: item.media_product_type === 'REELS', - isCarousel: item.media_type === 'CAROUSEL_ALBUM', - likes: String(item.like_count || 0), - comments: String(item.comments_count || 0), - caption: item.caption || 'Instagram media', - }))) - } + if (media) setLivePosts(mapLiveMedia(media as LiveInstagramMedia[])) } void loadPermissionedFeed() return () => { active = false } }, []) - const feed = livePosts.length ? livePosts : INSTAGRAM_GRID + const feed = livePosts const visibleFeed = activeTab === 'posts' ? feed.filter((post) => !post.isReel) : activeTab === 'reels'