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