From cbb6f6c158ca541aae34f3b677308a67cf093cd8 Mon Sep 17 00:00:00 2001 From: Danny White <3104761+dnywh@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:12:39 +1000 Subject: [PATCH] wip: poc chart --- .../components/SurveyResults/SurveyChart.tsx | 74 +++++++++++++++---- .../charts/AcceleratorParticipationChart.tsx | 43 ++++++----- 2 files changed, 80 insertions(+), 37 deletions(-) diff --git a/apps/www/components/SurveyResults/SurveyChart.tsx b/apps/www/components/SurveyResults/SurveyChart.tsx index 377a083eb27..aec3252b496 100644 --- a/apps/www/components/SurveyResults/SurveyChart.tsx +++ b/apps/www/components/SurveyResults/SurveyChart.tsx @@ -115,8 +115,14 @@ function useFilterOptions(filterColumns: string[]) { return { filters } } -// Custom hook to fetch survey data using SQL query via RPC -function useSurveyData(sqlQuery: string, shouldFetch: boolean) { +// Custom hook to fetch survey data using SQL query via RPC or function call +function useSurveyData( + sqlQuery: string, + shouldFetch: boolean, + functionName?: string, + functionParams?: (activeFilters: Record) => Record, + activeFilters?: Record +) { const [chartData, setChartData] = useState([]) const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) @@ -131,10 +137,30 @@ function useSurveyData(sqlQuery: string, shouldFetch: boolean) { // console.log('Executing SQL query:', sqlQuery) - // Execute the SQL query using Supabase RPC - const { data, error: fetchError } = await externalSupabase.rpc('execute_sql', { - query: sqlQuery, - }) + let data, fetchError + + if (functionName && functionParams && activeFilters) { + // Use the safer function approach + console.log('Active filters:', activeFilters) + const functionParamsData = functionParams(activeFilters) + console.log('Calling function:', functionName, 'with params:', functionParamsData) + const { data: functionData, error: functionError } = await externalSupabase.rpc( + functionName, + functionParamsData + ) + console.log('Function response:', functionData, 'error:', functionError) + data = functionData + fetchError = functionError + } else if (sqlQuery) { + // Fallback to the original RPC approach (for backward compatibility) + const { data: sqlData, error: sqlError } = await externalSupabase.rpc('execute_sql', { + query: sqlQuery, + }) + data = sqlData + fetchError = sqlError + } else { + throw new Error('No data source specified') + } if (fetchError) { console.error('Error executing SQL query:', fetchError) @@ -145,15 +171,19 @@ function useSurveyData(sqlQuery: string, shouldFetch: boolean) { console.log('Raw data from SQL query:', data) // Calculate total for percentage calculation - const total = data.reduce((sum: number, row: any) => sum + parseInt(row.total), 0) + const total = data.reduce( + (sum: number, row: any) => sum + parseInt(row.count || row.total), + 0 + ) // Transform the data to match chart format const processedData = data.map((row: any) => { - const rawPercentage = total > 0 ? (parseInt(row.total) / total) * 100 : 0 + const count = parseInt(row.count || row.total) + const rawPercentage = total > 0 ? (count / total) * 100 : 0 const roundedPercentage = Math.round(rawPercentage) return { - label: row.label || row.value || row[Object.keys(row)[0]], // Get the first column as label + label: row.accelerator || row.label || row.value || row[Object.keys(row)[0]], // Get the first column as label value: roundedPercentage, rawValue: rawPercentage, // Keep the raw value for bar scaling } @@ -170,7 +200,7 @@ function useSurveyData(sqlQuery: string, shouldFetch: boolean) { } fetchData() - }, [sqlQuery, shouldFetch]) + }, [sqlQuery, shouldFetch, functionName, activeFilters]) return { chartData, isLoading, error } } @@ -179,7 +209,9 @@ interface SurveyChartProps { title: string targetColumn: string filterColumns: string[] - generateSQLQuery: (activeFilters: Record) => string + generateSQLQuery?: (activeFilters: Record) => string + functionName?: string + functionParams?: (activeFilters: Record) => Record } export function SurveyChart({ @@ -187,6 +219,8 @@ export function SurveyChart({ targetColumn, filterColumns, generateSQLQuery, + functionName, + functionParams, }: SurveyChartProps) { const [isInView, setIsInView] = useState(false) const chartRef = useRef(null) @@ -235,11 +269,15 @@ export function SurveyChart({ ) ) - // Generate the SQL query string - const sqlQuery = generateSQLQuery(activeFilters) + // Generate the SQL query string or function parameters + const sqlQuery = generateSQLQuery ? generateSQLQuery(activeFilters) : '' // Use the custom hook to fetch data - const { chartData, isLoading: dataLoading, error: dataError } = useSurveyData(sqlQuery, isInView) + const { + chartData, + isLoading: dataLoading, + error: dataError, + } = useSurveyData(sqlQuery, isInView, functionName, functionParams, activeFilters) // Reset animation state when filters change useEffect(() => { @@ -446,7 +484,13 @@ export function SurveyChart({ ) : (
- {sqlQuery} + {functionName ? ( + + {`// Function call: ${functionName}(${JSON.stringify(functionParams ? functionParams(activeFilters) : {}, null, 2)})`} + + ) : ( + {sqlQuery} + )}
)} diff --git a/apps/www/components/SurveyResults/charts/AcceleratorParticipationChart.tsx b/apps/www/components/SurveyResults/charts/AcceleratorParticipationChart.tsx index cb17c715db3..b05498f26cf 100644 --- a/apps/www/components/SurveyResults/charts/AcceleratorParticipationChart.tsx +++ b/apps/www/components/SurveyResults/charts/AcceleratorParticipationChart.tsx @@ -1,26 +1,24 @@ -import { SurveyChart, buildWhereClause } from '../SurveyChart' +import { SurveyChart } from '../SurveyChart' -function generateAcceleratorParticipationSQL(activeFilters: Record) { - const whereClause = buildWhereClause(activeFilters, ['accelerator_participation IS NOT NULL']) +// Helper function to convert filters to the format expected by the database function +function buildFunctionParams(activeFilters: Record) { + const params: Record = {} - return `WITH accelerator_mapping AS ( - SELECT - accelerator_participation, - CASE - WHEN accelerator_participation IN ('YC', 'Techstars', 'EF', '500 Global', 'Plug and Play', 'Antler') THEN accelerator_participation - WHEN accelerator_participation = 'Did not participate in an accelerator' THEN NULL - ELSE 'Other' - END AS accelerator_clean - FROM responses_2025 - ${whereClause} -) -SELECT - accelerator_clean AS accelerator_participation, - COUNT(*) AS total -FROM accelerator_mapping -WHERE accelerator_clean IS NOT NULL -GROUP BY accelerator_clean -ORDER BY total DESC;` + // Convert single values to arrays for the function parameters + if (activeFilters.person_age && activeFilters.person_age !== 'unset') { + params.person_age_filter = [activeFilters.person_age] + } + if (activeFilters.location && activeFilters.location !== 'unset') { + params.location_filter = [activeFilters.location] + } + if (activeFilters.money_raised && activeFilters.money_raised !== 'unset') { + params.money_raised_filter = [activeFilters.money_raised] + } + // if (activeFilters.team_size && activeFilters.team_size !== 'unset') { + // params.team_size_filter = [activeFilters.team_size] + // } + + return params } export function AcceleratorParticipationChart() { @@ -29,7 +27,8 @@ export function AcceleratorParticipationChart() { title="If your startup has participated in an accelerator, which one?" targetColumn="accelerator_participation" filterColumns={['person_age', 'location', 'money_raised']} - generateSQLQuery={generateAcceleratorParticipationSQL} + functionName="get_accelerator_stats" + functionParams={buildFunctionParams} /> ) }