veza/apps/web/src/components/settings/cloud/CloudIntegrationView.tsx

144 lines
8.4 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
import { Card } from '../../ui/card';
import { Button } from '../../ui/button';
import { Input } from '../../ui/input';
import { Cloud, CheckCircle, RefreshCw, Server, Shield } from 'lucide-react';
import { useToast } from '../../../context/ToastContext';
import { ProgressBar } from '../../ui/progress';
export const CloudIntegrationView: React.FC = () => {
const { addToast } = useToast();
const [isConnected, setIsConnected] = useState(false);
const [url, setUrl] = useState('');
const [username, setUsername] = useState('');
const [autoSync, setAutoSync] = useState(true);
const handleConnect = () => {
if (!url || !username) return;
// Simulate connection
addToast("Connecting to Nextcloud...", "info");
setTimeout(() => {
setIsConnected(true);
addToast("Connected to Cloud Storage", "success");
}, 1500);
};
return (
<div className="max-w-4xl mx-auto space-y-8 animate-fadeIn">
{/* Connection Status */}
<Card variant="default" className="border-t-4 border-t-kodo-cyan">
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
<div className="flex items-center gap-4">
<div className={`w-16 h-16 rounded-full flex items-center justify-center ${isConnected ? 'bg-kodo-cyan text-black' : 'bg-gray-700 text-gray-400'}`}>
<Cloud className="w-8 h-8" />
</div>
<div>
<h2 className="text-2xl font-bold text-white">Nextcloud Integration</h2>
<p className="text-gray-400 text-sm">Sync your projects, samples, and presets.</p>
</div>
</div>
{isConnected && (
<div className="flex items-center gap-2 text-kodo-lime bg-kodo-lime/10 px-4 py-2 rounded-lg border border-kodo-lime/20">
<CheckCircle className="w-5 h-5" /> Connected
</div>
)}
</div>
{!isConnected ? (
<div className="mt-8 space-y-4 max-w-md">
<Input label="Server URL" placeholder="https://cloud.example.com" value={url} onChange={(e) => setUrl(e.target.value)} icon={<GlobeIcon className="w-4 h-4" />} />
<Input label="Username" placeholder="user@example.com" value={username} onChange={(e) => setUsername(e.target.value)} icon={<UserIcon className="w-4 h-4" />} />
<Input label="Password / App Token" type="password" placeholder="••••••••" icon={<LockIcon className="w-4 h-4" />} />
<Button variant="primary" className="w-full" onClick={handleConnect}>Connect Account</Button>
</div>
) : (
<div className="mt-8 grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="bg-kodo-ink p-4 rounded-lg border border-kodo-steel text-center">
<Server className="w-6 h-6 text-kodo-cyan mx-auto mb-2" />
<div className="text-sm font-bold text-white">{url}</div>
<div className="text-xs text-gray-500">Host</div>
</div>
<div className="bg-kodo-ink p-4 rounded-lg border border-kodo-steel text-center">
<RefreshCw className="w-6 h-6 text-kodo-gold mx-auto mb-2" />
<div className="text-sm font-bold text-white">Every 15 mins</div>
<div className="text-xs text-gray-500">Sync Frequency</div>
</div>
<div className="bg-kodo-ink p-4 rounded-lg border border-kodo-steel text-center">
<Shield className="w-6 h-6 text-kodo-lime mx-auto mb-2" />
<div className="text-sm font-bold text-white">Encrypted</div>
<div className="text-xs text-gray-500">Status</div>
</div>
</div>
)}
</Card>
{/* Sync Settings */}
{isConnected && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<Card variant="default">
<h3 className="font-bold text-white mb-4 border-b border-kodo-steel pb-2">Sync Preferences</h3>
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<div className="text-sm text-white font-bold">Auto-Sync</div>
<div className="text-xs text-gray-400">Automatically upload new projects</div>
</div>
<div
onClick={() => setAutoSync(!autoSync)}
className={`w-10 h-5 rounded-full relative cursor-pointer transition-colors ${autoSync ? 'bg-kodo-cyan' : 'bg-gray-600'}`}
>
<div className={`absolute top-1 w-3 h-3 bg-white rounded-full transition-all ${autoSync ? 'left-6' : 'left-1'}`}></div>
</div>
</div>
<div>
<label className="block text-xs font-bold text-gray-400 uppercase mb-2">Sync Frequency</label>
<select className="w-full bg-kodo-ink border border-kodo-steel rounded p-2 text-white outline-none focus:border-kodo-cyan">
<option>Every 15 minutes</option>
<option>Hourly</option>
<option>Daily</option>
<option>Manual Only</option>
</select>
</div>
<div>
<label className="block text-xs font-bold text-gray-400 uppercase mb-2">Selective Sync</label>
<div className="flex gap-2">
{['Projects', 'Samples', 'Presets'].map(type => (
<span key={type} className="px-3 py-1 bg-kodo-slate rounded text-xs text-white border border-kodo-steel cursor-pointer hover:border-kodo-cyan">
{type}
</span>
))}
</div>
</div>
</div>
</Card>
<Card variant="default">
<h3 className="font-bold text-white mb-4 border-b border-kodo-steel pb-2">Storage Quota</h3>
<div className="space-y-6">
<div className="text-center">
<div className="text-4xl font-mono font-bold text-white mb-1">65.4 GB</div>
<div className="text-sm text-gray-400">used of 100 GB</div>
</div>
<ProgressBar value={65.4} color="cyan" />
<div className="text-xs text-gray-500 flex justify-between">
<span>0 GB</span>
<span>100 GB</span>
</div>
<Button variant="gaming" className="w-full">UPGRADE STORAGE</Button>
</div>
</Card>
</div>
)}
</div>
);
};
// Helper icons
const GlobeIcon = ({className}:{className?:string}) => <svg className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>;
const UserIcon = ({className}:{className?:string}) => <svg className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>;
const LockIcon = ({className}:{className?:string}) => <svg className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>;