Files
configucci/src/componets/FileChooser.tsx
2026-02-20 10:19:27 +03:00

123 lines
3.7 KiB
TypeScript

import { useRef } from 'react';
import { Upload, Download, FilePlus, File } from 'lucide-react';
import { Button } from '../components/ui';
import { Config } from '../models/Config';
import { ConfigReader } from '../models/ConfigReader';
import { ConfigBuilder } from '../builders/ConfigBuilder';
import { Env } from '../models/Env';
interface FileChooserProps {
onSelected: (config: Config) => void;
config?: Config;
}
export function FileChooser({ onSelected, config }: FileChooserProps) {
const fileInputRef = useRef<HTMLInputElement>(null);
async function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
const file = event.target.files?.[0];
if (!file) return;
console.log(file.name, file.type, file.size, 'supported:', ConfigReader.isSupportedFormat(file));
const reader = new ConfigReader();
const cfg = await reader.parseFromFile(file);
if (cfg !== null) {
onSelected(cfg);
}
// Reset input
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
}
function handleNew() {
const cfg = new Config();
cfg.setEnvs([new Env(0, 'DEFAULT', [])]);
cfg.setTemplate('{}');
onSelected(cfg);
}
function handleDownload() {
if (!config) {
alert('No configuration loaded');
return;
}
const xmlContent = ConfigBuilder.buildFullXml(config);
const filename = ConfigBuilder.generateFilename();
const blob = new Blob([xmlContent], { type: 'text/xml' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
const hasConfig = !!config && !config.isEmpty();
return (
<div className="bg-white rounded-xl shadow-md p-4 border border-slate-200">
<div className="flex items-center gap-4 flex-wrap">
{/* Logo/Brand */}
<div className="flex items-center gap-2">
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center">
<File className="w-6 h-6 text-white" />
</div>
<span className="font-bold text-xl text-slate-800">Configucci</span>
</div>
<div className="h-8 w-px bg-slate-200" />
{/* Action Buttons */}
<div className="flex items-center gap-2 flex-1">
<Button
variant="primary"
onClick={handleNew}
icon={FilePlus}
size="sm"
>
New Config
</Button>
<Button
variant="success"
onClick={handleDownload}
icon={Download}
size="sm"
disabled={!hasConfig}
title={hasConfig ? 'Download full config template' : 'Load or create a config first'}
>
Download
</Button>
<span className="text-slate-400 text-sm">or</span>
{/* File Upload */}
<div className="flex-1">
<label
className="flex items-center justify-center gap-2 px-4 py-2 border-2 border-dashed border-slate-300 rounded-lg cursor-pointer hover:border-blue-400 hover:bg-blue-50 transition-all duration-200"
>
<Upload className="w-4 h-4 text-slate-400" />
<span className="text-sm text-slate-600">Upload XML Config</span>
<input
ref={fileInputRef}
type="file"
className="hidden"
accept=".xml,text/xml"
onChange={handleFileChange}
/>
</label>
</div>
</div>
</div>
</div>
);
}