Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/app/PageClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ interface PageClientProps {
settings?: Partial<SiteSettings> | null
testimonials?: Testimonial[]
posts?: BlogPost[]
instagramAccount?: any | null
instagramMedia?: any[]
isAdminPreview?: boolean
}

Expand All @@ -45,6 +47,8 @@ export default function PageClient({
settings: settingsInput,
testimonials = [],
posts = [],
instagramAccount = null,
instagramMedia = [],
isAdminPreview = false,
}: PageClientProps) {
const settings = mergeSiteSettings(settingsInput)
Expand Down Expand Up @@ -145,7 +149,7 @@ export default function PageClient({
>
<PortfolioShowcase projects={projects} technologies={technologies} />
<PerspectiveImage3DWall />
<InstagramPostGallery />
<InstagramPostGallery initialAccount={instagramAccount} initialMedia={instagramMedia} />
</motion.div>

{settings.show_testimonials ? (
Expand Down
10 changes: 9 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
Expand All @@ -56,6 +62,8 @@ export default async function Home() {
settings={settings}
testimonials={testimonials}
posts={posts}
instagramAccount={instagramAccount}
instagramMedia={instagramMedia}
isAdminPreview={settings.maintenance_mode && isAdmin}
/>
);
Expand Down
50 changes: 34 additions & 16 deletions src/components/sections/InstagramPostGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [
Expand Down Expand Up @@ -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<GridPost[]>([])
const [liveAccount, setLiveAccount] = useState<LiveInstagramAccount | null>(null)
const [livePosts, setLivePosts] = useState<GridPost[]>(() => mapLiveMedia(initialMedia))
const [liveAccount, setLiveAccount] = useState<LiveInstagramAccount | null>(initialAccount)
const { playClick, playHover } = useAudio()
const profileUrl = `https://www.instagram.com/${liveAccount?.username || 'sahad_____sha'}/`

Expand All @@ -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'
Expand Down