148 lines
No EOL
5.2 KiB
TypeScript
148 lines
No EOL
5.2 KiB
TypeScript
import React from 'react';
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { Settings as SettingsIcon, Save, ToggleLeft, ToggleRight } from 'lucide-react';
|
|
import { apiClient } from '../lib/api';
|
|
|
|
const Settings: React.FC = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
const { data: settings, isLoading, error } = useQuery({
|
|
queryKey: ['settings'],
|
|
queryFn: () => apiClient.getSettings(),
|
|
});
|
|
|
|
const updateMutation = useMutation({
|
|
mutationFn: (data: any) => apiClient.updateSettings(data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['settings'] });
|
|
},
|
|
});
|
|
|
|
const handleToggle = (key: string, value: boolean) => {
|
|
updateMutation.mutate({ [key]: value });
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="p-6">
|
|
<div className="animate-pulse">
|
|
<div className="h-8 bg-gray-200 rounded w-1/4 mb-6"></div>
|
|
<div className="space-y-6">
|
|
<div className="bg-white p-6 rounded-lg shadow">
|
|
<div className="h-4 bg-gray-200 rounded w-1/3 mb-4"></div>
|
|
<div className="space-y-4">
|
|
<div className="h-12 bg-gray-200 rounded"></div>
|
|
<div className="h-12 bg-gray-200 rounded"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="p-6">
|
|
<div className="bg-red-50 border border-red-200 rounded-md p-4">
|
|
<p className="text-red-600">Failed to load settings</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-6">
|
|
<div className="mb-8">
|
|
<h1 className="text-2xl font-bold text-gray-900">Settings</h1>
|
|
<p className="mt-1 text-sm text-gray-500">
|
|
Configure your system preferences
|
|
</p>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
{/* Article Processing Settings */}
|
|
<div className="bg-white rounded-lg shadow">
|
|
<div className="px-6 py-4 border-b border-gray-200">
|
|
<h2 className="text-lg font-medium text-gray-900 flex items-center">
|
|
<SettingsIcon className="h-5 w-5 mr-2" />
|
|
Article Processing
|
|
</h2>
|
|
<p className="mt-1 text-sm text-gray-500">
|
|
Control how articles are processed and handled
|
|
</p>
|
|
</div>
|
|
<div className="px-6 py-4 space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-900">
|
|
Article Processing Enabled
|
|
</h3>
|
|
<p className="text-sm text-gray-500">
|
|
Enable automatic fetching and processing of articles from feeds
|
|
</p>
|
|
</div>
|
|
<button
|
|
onClick={() => handleToggle('article_processing_enabled', !settings?.article_processing_enabled)}
|
|
disabled={updateMutation.isPending}
|
|
className="flex-shrink-0"
|
|
>
|
|
{settings?.article_processing_enabled ? (
|
|
<ToggleRight className="h-6 w-6 text-green-500" />
|
|
) : (
|
|
<ToggleLeft className="h-6 w-6 text-gray-300" />
|
|
)}
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-900">
|
|
Publishing Approvals Required
|
|
</h3>
|
|
<p className="text-sm text-gray-500">
|
|
Require manual approval before articles are published to platforms
|
|
</p>
|
|
</div>
|
|
<button
|
|
onClick={() => handleToggle('enable_publishing_approvals', !settings?.publishing_approvals_enabled)}
|
|
disabled={updateMutation.isPending}
|
|
className="flex-shrink-0"
|
|
>
|
|
{settings?.publishing_approvals_enabled ? (
|
|
<ToggleRight className="h-6 w-6 text-green-500" />
|
|
) : (
|
|
<ToggleLeft className="h-6 w-6 text-gray-300" />
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Status indicator */}
|
|
{updateMutation.isPending && (
|
|
<div className="bg-blue-50 border border-blue-200 rounded-md p-4">
|
|
<div className="flex items-center">
|
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600 mr-2"></div>
|
|
<p className="text-blue-600 text-sm">Updating settings...</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{updateMutation.isError && (
|
|
<div className="bg-red-50 border border-red-200 rounded-md p-4">
|
|
<p className="text-red-600 text-sm">Failed to update settings. Please try again.</p>
|
|
</div>
|
|
)}
|
|
|
|
{updateMutation.isSuccess && (
|
|
<div className="bg-green-50 border border-green-200 rounded-md p-4">
|
|
<p className="text-green-600 text-sm">Settings updated successfully!</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Settings; |