From 2ebb2eafec0b6e91a47c85818ab29cac7a19b760 Mon Sep 17 00:00:00 2001
From: "gpt-engineer-app[bot]"
<159125892+gpt-engineer-app[bot]@users.noreply.github.com>
Date: Tue, 28 Oct 2025 19:14:51 +0000
Subject: [PATCH] feat: Add user profile data to contact submissions
---
src/integrations/supabase/types.ts | 9 +++
src/pages/admin/AdminContact.tsx | 73 +++++++++++++++++++
.../functions/send-contact-message/index.ts | 40 +++++++++-
...1_ab23c579-d467-4a68-bcf9-bd3abc7fc250.sql | 9 +++
4 files changed, 130 insertions(+), 1 deletion(-)
create mode 100644 supabase/migrations/20251028191331_ab23c579-d467-4a68-bcf9-bd3abc7fc250.sql
diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts
index af3589b1..c9c5efc6 100644
--- a/src/integrations/supabase/types.ts
+++ b/src/integrations/supabase/types.ts
@@ -538,6 +538,9 @@ export type Database = {
response_count: number | null
status: string
subject: string
+ submitter_profile_data: Json | null
+ submitter_reputation: number | null
+ submitter_username: string | null
thread_id: string | null
ticket_number: string | null
updated_at: string
@@ -560,6 +563,9 @@ export type Database = {
response_count?: number | null
status?: string
subject: string
+ submitter_profile_data?: Json | null
+ submitter_reputation?: number | null
+ submitter_username?: string | null
thread_id?: string | null
ticket_number?: string | null
updated_at?: string
@@ -582,6 +588,9 @@ export type Database = {
response_count?: number | null
status?: string
subject?: string
+ submitter_profile_data?: Json | null
+ submitter_reputation?: number | null
+ submitter_username?: string | null
thread_id?: string | null
ticket_number?: string | null
updated_at?: string
diff --git a/src/pages/admin/AdminContact.tsx b/src/pages/admin/AdminContact.tsx
index 3b949723..d22b884b 100644
--- a/src/pages/admin/AdminContact.tsx
+++ b/src/pages/admin/AdminContact.tsx
@@ -18,6 +18,9 @@ import {
Reply,
Copy,
Check,
+ User,
+ Award,
+ TrendingUp,
} from 'lucide-react';
import { supabase } from '@/integrations/supabase/client';
import { Button } from '@/components/ui/button';
@@ -48,6 +51,7 @@ import {
import { Badge } from '@/components/ui/badge';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { ScrollArea } from '@/components/ui/scroll-area';
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { useTheme } from '@/components/theme/ThemeProvider';
import { useUserRole } from '@/hooks/useUserRole';
import { handleError, handleSuccess } from '@/lib/errorHandler';
@@ -61,6 +65,20 @@ interface ContactSubmission {
created_at: string;
updated_at: string;
user_id: string | null;
+ submitter_username: string | null;
+ submitter_reputation: number | null;
+ submitter_profile_data: {
+ display_name?: string;
+ member_since?: string;
+ stats?: {
+ rides: number;
+ coasters: number;
+ parks: number;
+ reviews: number;
+ };
+ reputation?: number;
+ avatar_url?: string;
+ } | null;
name: string;
email: string;
subject: string;
@@ -683,6 +701,61 @@ export default function AdminContact() {
+ {/* User Context Section */}
+ {selectedSubmission.submitter_profile_data && (
+
+
+
+ Submitter Context
+
+
+
+ {selectedSubmission.submitter_profile_data.avatar_url && (
+
+ )}
+
+ {selectedSubmission.submitter_username?.[0]?.toUpperCase() || 'U'}
+
+
+
+
+
+ @{selectedSubmission.submitter_username}
+
+ {selectedSubmission.submitter_profile_data.display_name && (
+
+ ({selectedSubmission.submitter_profile_data.display_name})
+
+ )}
+
+
+ {selectedSubmission.submitter_reputation} rep
+
+
+ {selectedSubmission.submitter_profile_data.member_since && (
+
+ Member since {format(new Date(selectedSubmission.submitter_profile_data.member_since), 'MMM d, yyyy')}
+
+ )}
+ {selectedSubmission.submitter_profile_data.stats && (
+
+
+
+ {selectedSubmission.submitter_profile_data.stats.rides} rides
+
+ •
+ {selectedSubmission.submitter_profile_data.stats.coasters} coasters
+ •
+ {selectedSubmission.submitter_profile_data.stats.parks} parks
+ •
+ {selectedSubmission.submitter_profile_data.stats.reviews} reviews
+
+ )}
+
+
+
+ )}
+
{/* Subject & Category */}
diff --git a/supabase/functions/send-contact-message/index.ts b/supabase/functions/send-contact-message/index.ts
index 258f20be..b01e727a 100644
--- a/supabase/functions/send-contact-message/index.ts
+++ b/supabase/functions/send-contact-message/index.ts
@@ -124,9 +124,12 @@ const handler = async (req: Request): Promise => {
);
}
- // Get user ID if authenticated
+ // Get user ID and profile if authenticated
const authHeader = req.headers.get('Authorization');
let userId: string | null = null;
+ let submitterUsername: string | null = null;
+ let submitterReputation: number | null = null;
+ let submitterProfileData: Record | null = null;
if (authHeader) {
const supabaseClient = createClient(
@@ -137,6 +140,38 @@ const handler = async (req: Request): Promise => {
const { data: { user } } = await supabaseClient.auth.getUser();
userId = user?.id || null;
+
+ // Fetch user profile for enhanced context
+ if (userId) {
+ const { data: profile } = await supabase
+ .from('profiles')
+ .select('username, display_name, reputation_score, ride_count, coaster_count, park_count, review_count, created_at, avatar_url')
+ .eq('user_id', userId)
+ .single();
+
+ if (profile) {
+ submitterUsername = profile.username;
+ submitterReputation = profile.reputation_score || 0;
+ submitterProfileData = {
+ display_name: profile.display_name,
+ member_since: profile.created_at,
+ stats: {
+ rides: profile.ride_count || 0,
+ coasters: profile.coaster_count || 0,
+ parks: profile.park_count || 0,
+ reviews: profile.review_count || 0,
+ },
+ reputation: profile.reputation_score || 0,
+ avatar_url: profile.avatar_url
+ };
+
+ edgeLogger.info('Enhanced submission with user profile', {
+ requestId,
+ username: submitterUsername,
+ reputation: submitterReputation
+ });
+ }
+ }
}
// Insert contact submission (ticket number auto-generated by trigger)
@@ -144,6 +179,9 @@ const handler = async (req: Request): Promise => {
.from('contact_submissions')
.insert({
user_id: userId,
+ submitter_username: submitterUsername,
+ submitter_reputation: submitterReputation,
+ submitter_profile_data: submitterProfileData,
name: name.trim(),
email: email.trim().toLowerCase(),
subject: subject.trim(),
diff --git a/supabase/migrations/20251028191331_ab23c579-d467-4a68-bcf9-bd3abc7fc250.sql b/supabase/migrations/20251028191331_ab23c579-d467-4a68-bcf9-bd3abc7fc250.sql
new file mode 100644
index 00000000..9fbe182d
--- /dev/null
+++ b/supabase/migrations/20251028191331_ab23c579-d467-4a68-bcf9-bd3abc7fc250.sql
@@ -0,0 +1,9 @@
+-- Add user profile context columns to contact_submissions
+ALTER TABLE contact_submissions
+ ADD COLUMN submitter_username text,
+ ADD COLUMN submitter_reputation integer,
+ ADD COLUMN submitter_profile_data jsonb;
+
+COMMENT ON COLUMN contact_submissions.submitter_username IS 'Username snapshot at time of submission';
+COMMENT ON COLUMN contact_submissions.submitter_reputation IS 'Reputation score snapshot at time of submission';
+COMMENT ON COLUMN contact_submissions.submitter_profile_data IS 'Full profile snapshot (display_name, member_since, stats, avatar_url) at time of submission';
\ No newline at end of file