mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-29 05:47:06 -05:00
Compare commits
6 Commits
6acc1c97c7
...
4d21dc4435
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d21dc4435 | ||
|
|
cfda7e8d56 | ||
|
|
1c7ca8fe32 | ||
|
|
b3bb55ecd9 | ||
|
|
c8c210a6e5 | ||
|
|
2b8ee9061e |
@@ -1,4 +1,4 @@
|
||||
import { LayoutDashboard, FileText, Flag, Users, Settings, ArrowLeft, ScrollText, BookOpen } from 'lucide-react';
|
||||
import { LayoutDashboard, FileText, Flag, Users, Settings, ArrowLeft, ScrollText, BookOpen, Inbox } from 'lucide-react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { useUserRole } from '@/hooks/useUserRole';
|
||||
import { useSidebar } from '@/hooks/useSidebar';
|
||||
@@ -38,6 +38,11 @@ export function AdminSidebar() {
|
||||
url: '/admin/reports',
|
||||
icon: Flag,
|
||||
},
|
||||
{
|
||||
title: 'Inbox',
|
||||
url: '/admin/contact',
|
||||
icon: Inbox,
|
||||
},
|
||||
{
|
||||
title: 'System Log',
|
||||
url: '/admin/system-log',
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
ArrowUpRight,
|
||||
ArrowDownLeft,
|
||||
Loader2,
|
||||
RefreshCw,
|
||||
} from 'lucide-react';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -50,6 +51,7 @@ import { handleError, handleSuccess } from '@/lib/errorHandler';
|
||||
import { logger } from '@/lib/logger';
|
||||
import { contactCategories } from '@/lib/contactValidation';
|
||||
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
||||
import { AdminLayout } from '@/components/layout/AdminLayout';
|
||||
|
||||
interface ContactSubmission {
|
||||
id: string;
|
||||
@@ -86,7 +88,7 @@ interface EmailThread {
|
||||
export default function AdminContact() {
|
||||
const queryClient = useQueryClient();
|
||||
const { theme } = useTheme();
|
||||
const { isAdmin } = useUserRole();
|
||||
const { isAdmin, loading: rolesLoading } = useUserRole();
|
||||
const [statusFilter, setStatusFilter] = useState<string>('all');
|
||||
const [categoryFilter, setCategoryFilter] = useState<string>('all');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -97,23 +99,6 @@ export default function AdminContact() {
|
||||
const [emailThreads, setEmailThreads] = useState<EmailThread[]>([]);
|
||||
const [loadingThreads, setLoadingThreads] = useState(false);
|
||||
|
||||
// Admin-only access check
|
||||
if (!isAdmin()) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<Card className="max-w-md">
|
||||
<CardContent className="pt-6 text-center">
|
||||
<AlertCircle className="h-12 w-12 text-destructive mx-auto mb-4" />
|
||||
<h2 className="text-xl font-semibold mb-2">Access Denied</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Email response features are only available to administrators.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch contact submissions
|
||||
const { data: submissions, isLoading } = useQuery({
|
||||
queryKey: ['admin-contact-submissions', statusFilter, categoryFilter, searchQuery],
|
||||
@@ -275,6 +260,36 @@ export default function AdminContact() {
|
||||
return cat?.label || category;
|
||||
};
|
||||
|
||||
const handleRefreshSubmissions = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['admin-contact-submissions'] });
|
||||
};
|
||||
|
||||
// Show loading state while roles are being fetched
|
||||
if (rolesLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<p className="text-muted-foreground">Loading...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Admin-only access check (after loading complete)
|
||||
if (!isAdmin()) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<Card className="max-w-md">
|
||||
<CardContent className="pt-6 text-center">
|
||||
<AlertCircle className="h-12 w-12 text-destructive mx-auto mb-4" />
|
||||
<h2 className="text-xl font-semibold mb-2">Access Denied</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Email response features are only available to administrators.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Theme-aware EmailThreadItem component
|
||||
function EmailThreadItem({ thread }: { thread: EmailThread }) {
|
||||
const isOutbound = thread.direction === 'outbound';
|
||||
@@ -323,13 +338,24 @@ export default function AdminContact() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8 max-w-7xl">
|
||||
<AdminLayout>
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold mb-2">Contact Submissions</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Manage and respond to user contact form submissions
|
||||
</p>
|
||||
<div className="mb-8 flex items-start justify-between">
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold mb-2">Contact Submissions</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Manage and respond to user contact form submissions
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handleRefreshSubmissions}
|
||||
disabled={isLoading}
|
||||
title="Refresh submissions"
|
||||
>
|
||||
<RefreshCw className={`h-4 w-4 ${isLoading ? 'animate-spin' : ''}`} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
@@ -675,6 +701,6 @@ export default function AdminContact() {
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
-- Fix RLS policy that's causing "permission denied for table users" error
|
||||
-- The issue is the policy tries to SELECT from auth.users which isn't allowed
|
||||
|
||||
-- Drop the problematic policy
|
||||
DROP POLICY IF EXISTS "Users can view own contact submissions" ON public.contact_submissions;
|
||||
|
||||
-- Recreate it using auth.jwt() to get email instead of querying auth.users
|
||||
CREATE POLICY "Users can view own contact submissions"
|
||||
ON public.contact_submissions
|
||||
FOR SELECT
|
||||
TO public
|
||||
USING (
|
||||
user_id = auth.uid()
|
||||
OR
|
||||
(auth.uid() IS NOT NULL AND email = (auth.jwt() ->> 'email'))
|
||||
);
|
||||
Reference in New Issue
Block a user