diff --git a/app/admin/settings/page.tsx b/app/admin/settings/page.tsx index 26de44b..dc05fc7 100644 --- a/app/admin/settings/page.tsx +++ b/app/admin/settings/page.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useState, useEffect } from 'react'; import { supabase } from '../../lib/supabaseClient'; -import { Settings, Shield, Users, FileText, Bell, Database, Lock, Save, Eye, EyeOff } from 'lucide-react'; +import { Settings, Shield, Users, FileText, Bell, Database, Lock, Save, Eye, EyeOff, FileEdit } from 'lucide-react'; import { toast, ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import { useAuth } from '../../context/AuthContext'; @@ -19,6 +19,14 @@ interface AdminSettings { contact_email: string; } +interface TermsAndConditions { + id: string | null; + title: string; + content: string; + version: number; + last_updated: string; +} + interface SystemStats { database_size: string; storage_used: string; @@ -43,15 +51,19 @@ const AdminSettingsPage = () => { const [systemStats, setSystemStats] = useState(null); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); - const [activeTab, setActiveTab] = useState<'general' | 'listings' | 'users' | 'system' | 'security'>('general'); + const [activeTab, setActiveTab] = useState<'general' | 'listings' | 'users' | 'system' | 'security' | 'terms'>('general'); const [newAdminEmail, setNewAdminEmail] = useState(''); const [adminUsers, setAdminUsers] = useState([]); const [showApiKeys, setShowApiKeys] = useState(false); + const [terms, setTerms] = useState(null); + const [termsLoading, setTermsLoading] = useState(false); + const [termsSaving, setTermsSaving] = useState(false); useEffect(() => { fetchSettings(); fetchSystemStats(); fetchAdminUsers(); + fetchTerms(); }, []); const fetchSettings = async () => { @@ -99,6 +111,64 @@ const AdminSettingsPage = () => { } }; + const fetchTerms = async () => { + try { + setTermsLoading(true); + const response = await fetch('/api/terms'); + if (!response.ok) { + throw new Error('Failed to fetch terms'); + } + const data = await response.json(); + setTerms(data); + } catch (error) { + console.error('Error fetching terms:', error); + toast.error('Failed to load terms and conditions'); + } finally { + setTermsLoading(false); + } + }; + + const saveTerms = async () => { + if (!terms) return; + + try { + setTermsSaving(true); + + // Get the current session token + const { data: { session } } = await supabase.auth.getSession(); + if (!session) { + toast.error('You must be logged in to save terms'); + return; + } + + const response = await fetch('/api/terms', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${session.access_token}`, + }, + body: JSON.stringify({ + title: terms.title, + content: terms.content, + }), + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to save terms'); + } + + const updatedTerms = await response.json(); + setTerms(updatedTerms); + toast.success('Terms and conditions updated successfully'); + } catch (error) { + console.error('Error saving terms:', error); + toast.error(error instanceof Error ? error.message : 'Failed to save terms and conditions'); + } finally { + setTermsSaving(false); + } + }; + const fetchAdminUsers = async () => { try { // First try to fetch with is_admin column @@ -246,7 +316,8 @@ const AdminSettingsPage = () => { { id: 'listings', label: 'Listings', icon: FileText }, { id: 'users', label: 'Users', icon: Users }, { id: 'system', label: 'System', icon: Database }, - { id: 'security', label: 'Security', icon: Lock } + { id: 'security', label: 'Security', icon: Lock }, + { id: 'terms', label: 'Terms', icon: FileEdit } ] as const; if (loading) { @@ -606,6 +677,81 @@ const AdminSettingsPage = () => { )} + + {/* Terms and Conditions Editor */} + {activeTab === 'terms' && ( +
+
+

Terms and Conditions Editor

+ + {termsLoading ? ( +
+
+ Loading terms... +
+ ) : terms ? ( +
+
+
+

Current Version

+ v{terms.version} +
+

+ Last updated: {new Date(terms.last_updated).toLocaleString()} +

+
+ +
+ + setTerms({...terms, title: e.target.value})} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#bf5700] focus:border-transparent" + placeholder="Terms and Conditions" + /> +
+ +
+ +