1+ CREATE OR REPLACE FUNCTION get_user_profile_stats (p_days INT DEFAULT 90 )
2+ RETURNS JSON
3+ LANGUAGE plpgsql
4+ SECURITY INVOKER
5+ AS $$
6+ DECLARE
7+ v_user_id UUID;
8+ v_username TEXT ;
9+ v_avatar TEXT ;
10+ v_tasks_done INT ;
11+ v_current_streak INT ;
12+ v_heatmap_data JSON;
13+ BEGIN
14+ v_user_id := auth .uid ();
15+
16+ IF v_user_id IS NULL THEN
17+ RAISE EXCEPTION ' User not authenticated' ;
18+ END IF;
19+
20+ SELECT username, avatar INTO v_username, v_avatar
21+ FROM public .profile
22+ WHERE id = v_user_id;
23+
24+ SELECT COUNT (* ) INTO v_tasks_done
25+ FROM public .task
26+ WHERE profile_id = v_user_id AND status = 1 ;
27+
28+ -- Get task done per day for heatmap
29+ SELECT json_object_agg(task_date::TEXT , task_count) INTO v_heatmap_data
30+ FROM (
31+ SELECT DATE (updated_at AT TIME ZONE ' Asia/Ho_Chi_Minh' ) AS task_date, COUNT (* ) AS task_count
32+ FROM public .task
33+ WHERE profile_id = v_user_id AND status = 1
34+ AND updated_at >= ((CURRENT_TIMESTAMP AT TIME ZONE ' Asia/Ho_Chi_Minh' )::DATE - (p_days || ' days' )::INTERVAL)
35+ GROUP BY DATE (updated_at AT TIME ZONE ' Asia/Ho_Chi_Minh' )
36+ ) t;
37+
38+ WITH completed_dates AS (
39+ SELECT DISTINCT DATE (updated_at AT TIME ZONE ' Asia/Ho_Chi_Minh' ) AS task_date
40+ FROM public .task
41+ WHERE profile_id = v_user_id AND status = 1
42+ ),
43+ streak_groups AS (
44+ SELECT task_date,
45+ task_date - (ROW_NUMBER() OVER (ORDER BY task_date))::INT AS grp
46+ FROM completed_dates
47+ ),
48+ streak_counts AS (
49+ SELECT grp, MAX (task_date) as end_date, COUNT (* ) as streak_length
50+ FROM streak_groups
51+ GROUP BY grp
52+ )
53+ SELECT COALESCE(MAX (streak_length), 0 ) INTO v_current_streak
54+ FROM streak_counts
55+ WHERE end_date >= ((CURRENT_TIMESTAMP AT TIME ZONE ' Asia/Ho_Chi_Minh' )::DATE - INTERVAL ' 1 day' );
56+
57+
58+ RETURN json_build_object(
59+ ' name' , COALESCE(v_username, ' Unknown User' ),
60+ ' avatarUrl' , COALESCE(v_avatar, ' ' ),
61+ ' tasksDone' , COALESCE(v_tasks_done, 0 ),
62+ ' streaks' , COALESCE(v_current_streak, 0 ),
63+ ' heatmapData' , COALESCE(v_heatmap_data, ' {}' ::JSON)
64+ );
65+ END;
66+ $$;
0 commit comments