From 31bfadf38a7edccba20eeb42dda7ccca27f6e83a Mon Sep 17 00:00:00 2001 From: Desktop Date: Thu, 13 Nov 2025 00:59:55 +0500 Subject: [PATCH] ind page --- frontend/src/pages/Reference/Industries.tsx | 164 ++++++++++++++++---- frontend/src/services/api.ts | 4 + 2 files changed, 135 insertions(+), 33 deletions(-) diff --git a/frontend/src/pages/Reference/Industries.tsx b/frontend/src/pages/Reference/Industries.tsx index cdee6ea1..7315be28 100644 --- a/frontend/src/pages/Reference/Industries.tsx +++ b/frontend/src/pages/Reference/Industries.tsx @@ -1,13 +1,20 @@ import { useState, useEffect } from 'react'; import PageMeta from '../../components/common/PageMeta'; import { useToast } from '../../components/ui/toast/ToastContainer'; -import { fetchIndustries, Industry } from '../../services/api'; +import { fetchIndustries, Industry, fetchSeedKeywords, SeedKeyword } from '../../services/api'; import { Card } from '../../components/ui/card'; import Badge from '../../components/ui/badge/Badge'; +import PageHeader from '../../components/common/PageHeader'; +import { PieChartIcon } from '../../icons'; + +interface IndustryWithData extends Industry { + keywordsCount: number; + topKeywords: SeedKeyword[]; +} export default function Industries() { const toast = useToast(); - const [industries, setIndustries] = useState([]); + const [industries, setIndustries] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { @@ -18,7 +25,40 @@ export default function Industries() { try { setLoading(true); const response = await fetchIndustries(); - setIndustries(response.industries || []); + const industriesList = response.industries || []; + + // First, fetch all seed keywords once (more efficient than per-industry) + // We'll fetch a larger sample to get accurate counts and top keywords + let allKeywords: SeedKeyword[] = []; + try { + const keywordsResponse = await fetchSeedKeywords({ + page_size: 1000, // Get a large sample for accurate counts + }); + allKeywords = keywordsResponse.results || []; + } catch (error) { + console.warn('Failed to fetch keywords, will show without keyword data:', error); + } + + // Process each industry with its keywords data + const industriesWithData = industriesList.map((industry) => { + // Filter keywords by industry name (matching industry.name) + const industryKeywords = allKeywords.filter( + (kw: SeedKeyword) => kw.industry_name === industry.name + ); + + // Sort by volume and get top 5 + const topKeywords = [...industryKeywords] + .sort((a, b) => (b.volume || 0) - (a.volume || 0)) + .slice(0, 5); + + return { + ...industry, + keywordsCount: industryKeywords.length, + topKeywords, + }; + }); + + setIndustries(industriesWithData); } catch (error: any) { toast.error(`Failed to load industries: ${error.message}`); } finally { @@ -27,38 +67,96 @@ export default function Industries() { }; return ( -
+ <> -
-

Industries

-

Global industry reference data

-
+ , color: 'blue' }} + /> +
+
+

+ Explore our comprehensive global database of industries, sectors, and high-volume keywords +

+
- {loading ? ( -
-
Loading...
-
- ) : ( -
- {industries.map((industry) => ( - -
-

{industry.name}

- - {industry.is_active ? 'Active' : 'Inactive'} - -
- {industry.description && ( -

{industry.description}

- )} -

- Sectors: {industry.sectors_count || 0} -

-
- ))} -
- )} -
+ {loading ? ( +
+
Loading industries...
+
+ ) : ( +
+ {industries.map((industry) => ( + + {/* Header */} +
+

+ {industry.name} +

+ {industry.is_active !== false && ( + + Active + + )} +
+ + {/* Description - Compact */} + {industry.description && ( +

+ {industry.description} +

+ )} + + {/* Stats Row - Compact */} +
+
+ + + + {industry.sectors?.length || industry.sectors_count || 0} + sectors +
+
+ + + + {industry.keywordsCount || 0} + keywords +
+
+ + {/* Top Keywords Section */} + {industry.topKeywords && industry.topKeywords.length > 0 && ( +
+

+ Top Keywords +

+
+ {industry.topKeywords.slice(0, 5).map((keyword, idx) => ( +
+ + {keyword.keyword} + + + {keyword.volume ? (keyword.volume >= 1000 ? `${(keyword.volume / 1000).toFixed(1)}k` : keyword.volume.toString()) : '-'} + +
+ ))} +
+
+ )} +
+ ))} +
+ )} +
+ ); } diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts index 78503767..fb3eff4d 100644 --- a/frontend/src/services/api.ts +++ b/frontend/src/services/api.ts @@ -1242,10 +1242,14 @@ export async function fetchSiteSectors(siteId: number): Promise { // Industries API functions export interface Industry { + id?: number; name: string; slug: string; description: string; sectors: Sector[]; + sectors_count?: number; + keywords_count?: number; + is_active?: boolean; } export interface Sector {