feat: implement analytics dashboard page with custom Recharts visualizations and Supabase RPC integration

This commit is contained in:
Poyraz
2026-06-17 09:20:21 +03:00
parent 3634b3a227
commit 3504a02229
8 changed files with 463 additions and 145 deletions
@@ -0,0 +1,161 @@
-- 0012_add_analytics_rpcs.sql
-- RPCs for Dashboard and Analytics aggregations to optimize frontend payload size
CREATE OR REPLACE FUNCTION public.get_dashboard_metrics(
p_start_date TIMESTAMP WITH TIME ZONE,
p_end_date TIMESTAMP WITH TIME ZONE
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_user_id UUID := auth.uid();
v_income NUMERIC;
v_expense NUMERIC;
v_net_profit NUMERIC;
v_active_projects INT;
v_completed_tasks INT;
v_avg_mood NUMERIC;
v_finance_trend JSONB;
v_mood_trend JSONB;
BEGIN
IF v_user_id IS NULL THEN
RAISE EXCEPTION 'Not authenticated';
END IF;
-- 1. Net Profit
SELECT COALESCE(SUM(amount), 0) INTO v_income
FROM finance_transactions
WHERE user_id = v_user_id AND type = 'income'
AND transaction_date >= p_start_date::date AND transaction_date <= p_end_date::date;
SELECT COALESCE(SUM(amount), 0) INTO v_expense
FROM finance_transactions
WHERE user_id = v_user_id AND type = 'expense'
AND transaction_date >= p_start_date::date AND transaction_date <= p_end_date::date;
v_net_profit := v_income - v_expense;
-- 2. Active Projects
SELECT COUNT(*) INTO v_active_projects
FROM projects
WHERE user_id = v_user_id AND status = 'active';
-- 3. Completed Tasks
SELECT COUNT(*) INTO v_completed_tasks
FROM tasks
WHERE user_id = v_user_id AND status = 'done'
AND COALESCE(updated_at, created_at) >= p_start_date AND COALESCE(updated_at, created_at) <= p_end_date;
-- 4. Average Mood
SELECT COALESCE(ROUND(AVG(mood_score)::numeric, 1), 0) INTO v_avg_mood
FROM daily_logs
WHERE user_id = v_user_id
AND log_date >= p_start_date::date AND log_date <= p_end_date::date;
-- 5. Finance Trend (group by date)
SELECT COALESCE(jsonb_agg(
jsonb_build_object(
'date', t.t_date,
'income', t.inc,
'expense', t.exp
)
), '[]'::jsonb) INTO v_finance_trend
FROM (
SELECT
transaction_date AS t_date,
SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) AS inc,
SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) AS exp
FROM finance_transactions
WHERE user_id = v_user_id
AND transaction_date >= p_start_date::date AND transaction_date <= p_end_date::date
GROUP BY transaction_date
ORDER BY transaction_date ASC
) t;
-- 6. Mood Trend
SELECT COALESCE(jsonb_agg(
jsonb_build_object(
'date', log_date,
'mood', mood_score,
'energy', energy_score
)
), '[]'::jsonb) INTO v_mood_trend
FROM (
SELECT log_date, mood_score, energy_score
FROM daily_logs
WHERE user_id = v_user_id
AND log_date >= p_start_date::date AND log_date <= p_end_date::date
ORDER BY log_date ASC
) m;
RETURN jsonb_build_object(
'netProfit', v_net_profit,
'activeProjectsCount', v_active_projects,
'completedTasksCount', v_completed_tasks,
'avgMood', v_avg_mood::text,
'financeTrend', v_finance_trend,
'moodTrend', v_mood_trend
);
END;
$$;
CREATE OR REPLACE FUNCTION public.get_analytics_metrics(
p_start_date TIMESTAMP WITH TIME ZONE,
p_end_date TIMESTAMP WITH TIME ZONE
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
v_user_id UUID := auth.uid();
v_project_income JSONB;
v_completed_tasks INT;
v_active_tasks INT;
BEGIN
IF v_user_id IS NULL THEN
RAISE EXCEPTION 'Not authenticated';
END IF;
-- 1. Project Income Data
SELECT COALESCE(jsonb_agg(
jsonb_build_object(
'name', t.p_name,
'value', t.total_amount
)
), '[]'::jsonb) INTO v_project_income
FROM (
SELECT
COALESCE(p.name, 'Bilinmeyen') AS p_name,
SUM(f.amount) AS total_amount
FROM finance_transactions f
LEFT JOIN projects p ON f.project_id = p.id
WHERE f.user_id = v_user_id AND f.type = 'income'
AND f.transaction_date >= p_start_date::date AND f.transaction_date <= p_end_date::date
GROUP BY p.name
ORDER BY total_amount DESC
) t;
-- 2. Task completion stats
SELECT COUNT(*) INTO v_completed_tasks
FROM tasks
WHERE user_id = v_user_id AND status = 'done'
AND COALESCE(due_at, created_at) >= p_start_date AND COALESCE(due_at, created_at) <= p_end_date;
SELECT COUNT(*) INTO v_active_tasks
FROM tasks
WHERE user_id = v_user_id AND status != 'done' AND status != 'cancelled'
AND COALESCE(due_at, created_at) >= p_start_date AND COALESCE(due_at, created_at) <= p_end_date;
RETURN jsonb_build_object(
'projectIncomeData', v_project_income,
'completedTasks', v_completed_tasks,
'activeTasks', v_active_tasks
);
END;
$$;