style(nextjs): changes settings llm selection layout

This commit is contained in:
sauravniraula 2025-07-23 00:10:41 +05:45
parent 801f103c2a
commit fad0e48437
No known key found for this signature in database
GPG key ID: 60FCC1B5A5E83326

View file

@ -1,8 +1,7 @@
"use client";
import React, { useState, useEffect } from "react";
import Header from "../dashboard/components/Header";
import Wrapper from "@/components/Wrapper";
import { Settings, Key, Loader2 } from "lucide-react";
import { Loader2, Download, CheckCircle } from "lucide-react";
import { toast } from "sonner";
import { RootState } from "@/store/store";
import { useSelector } from "react-redux";
@ -45,6 +44,14 @@ const SettingsPage = () => {
status: string;
done: boolean;
} | null>(null);
const [showDownloadModal, setShowDownloadModal] = useState<boolean>(false);
const downloadProgress = React.useMemo(() => {
if (downloadingModel && downloadingModel.downloaded !== null && downloadingModel.size !== null) {
return Math.round((downloadingModel.downloaded / downloadingModel.size) * 100);
}
return 0;
}, [downloadingModel?.downloaded, downloadingModel?.size]);
const handleSaveConfig = async () => {
try {
@ -55,17 +62,18 @@ const SettingsPage = () => {
isDisabled: true,
text: "Saving Configuration..."
}));
await handleSaveLLMConfig(llmConfig);
if (llmConfig.LLM === "ollama" && llmConfig.OLLAMA_MODEL) {
const isPulled = await checkIfSelectedOllamaModelIsPulled(llmConfig.OLLAMA_MODEL);
if (!isPulled) {
setShowDownloadModal(true);
await handleModelDownload();
}
}
toast.success("Configuration saved successfully");
toast.info("Configuration saved successfully");
setIsLoading(false);
setButtonState(prev => ({
...prev,
@ -76,7 +84,7 @@ const SettingsPage = () => {
router.back();
} catch (error) {
console.error("Error:", error);
toast.error(
toast.info(
error instanceof Error
? error.message
: "Failed to save configuration"
@ -97,6 +105,7 @@ const SettingsPage = () => {
} catch (error) {
console.error("Error downloading model:", error);
setDownloadingModel(null);
setShowDownloadModal(false);
}
};
@ -115,8 +124,9 @@ const SettingsPage = () => {
if (downloadingModel && downloadingModel.done) {
setTimeout(() => {
setShowDownloadModal(false);
setDownloadingModel(null);
toast.success("Model downloaded successfully!");
toast.info("Model downloaded successfully!");
}, 2000);
}
}, [downloadingModel]);
@ -132,64 +142,115 @@ const SettingsPage = () => {
}
return (
<div className="min-h-screen bg-[#E9E8F8] font-instrument_sans">
<div className="h-screen bg-gradient-to-b font-instrument_sans from-gray-50 to-white flex flex-col overflow-hidden">
<Header />
<Wrapper className="lg:w-[80%]">
<div className="py-8 space-y-6">
{/* Settings Header */}
<div className="flex items-center gap-3 mb-6">
<Settings className="w-8 h-8 text-blue-600" />
<h1 className="text-2xl font-semibold text-gray-900">Settings</h1>
</div>
<main className="flex-1 container mx-auto px-4 max-w-3xl overflow-hidden flex flex-col">
{/* LLM Selection Component */}
<div className="flex-1 overflow-hidden">
<LLMProviderSelection
initialLLMConfig={llmConfig}
onConfigChange={setLlmConfig}
buttonState={buttonState}
setButtonState={setButtonState}
/>
</div>
</main>
{/* API Configuration Section */}
<div className="bg-white rounded-xl shadow-sm p-6">
<div className="flex items-center gap-3 mb-6">
<Key className="w-5 h-5 text-blue-600" />
<h2 className="text-lg font-medium text-gray-900">
API Configuration
</h2>
</div>
{/* Fixed Bottom Button */}
<div className="flex-shrink-0 bg-white border-t border-gray-200 p-4">
<div className="container mx-auto max-w-3xl">
<button
onClick={handleSaveConfig}
disabled={buttonState.isDisabled}
className={`w-full font-semibold py-3 px-4 rounded-lg transition-all duration-500 ${buttonState.isDisabled
? "bg-gray-400 cursor-not-allowed"
: "bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 focus:ring-4 focus:ring-blue-200"
} text-white`}
>
{buttonState.isLoading ? (
<div className="flex items-center justify-center gap-2">
<Loader2 className="w-4 h-4 animate-spin" />
{buttonState.text}
</div>
) : (
buttonState.text
)}
</button>
</div>
</div>
{/* LLM Selection Component */}
<div className="h-[600px]">
<LLMProviderSelection
initialLLMConfig={llmConfig}
onConfigChange={setLlmConfig}
buttonState={buttonState}
setButtonState={setButtonState}
/>
</div>
{/* Download Progress Modal */}
{showDownloadModal && downloadingModel && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="bg-white/95 backdrop-blur-md rounded-xl shadow-2xl max-w-md w-full p-6 relative">
{/* Modal Content */}
<div className="text-center">
{/* Icon */}
<div className="mb-4">
{downloadingModel.done ? (
<CheckCircle className="w-12 h-12 text-green-600 mx-auto" />
) : (
<Download className="w-12 h-12 text-blue-600 mx-auto animate-pulse" />
)}
</div>
{/* Save Button */}
<button
onClick={handleSaveConfig}
disabled={buttonState.isDisabled}
className={`mt-8 w-full font-semibold py-3 px-4 rounded-lg transition-all duration-500 ${buttonState.isDisabled
? "bg-gray-400 cursor-not-allowed"
: "bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 focus:ring-4 focus:ring-blue-200"
} text-white`}
>
{buttonState.isLoading ? (
<div className="flex items-center justify-center gap-2">
<Loader2 className="w-4 h-4 animate-spin" />
{buttonState.text}
</div>
) : (
buttonState.text
)}
</button>
{/* Title */}
<h3 className="text-lg font-semibold text-gray-900 mb-2">
{downloadingModel.done ? "Download Complete!" : "Downloading Model"}
</h3>
{llmConfig.LLM === "ollama" &&
downloadingModel?.status &&
downloadingModel.status !== "pulled" && (
<div className="mt-3 text-sm bg-green-100 rounded-lg p-2 font-semibold capitalize text-center text-gray-600">
{downloadingModel.status}
{/* Model Name */}
<p className="text-sm text-gray-600 mb-6">
{llmConfig.OLLAMA_MODEL}
</p>
{/* Progress Bar */}
{downloadProgress > 0 && (
<div className="mb-4">
<div className="w-full bg-gray-200 rounded-full h-3 overflow-hidden">
<div
className="bg-blue-600 h-3 rounded-full transition-all duration-300 ease-out"
style={{ width: `${downloadProgress}%` }}
/>
</div>
<p className="text-sm text-gray-600 mt-2">
{downloadProgress}% Complete
</p>
</div>
)}
{/* Status */}
{downloadingModel.status && (
<div className="flex items-center justify-center gap-2 mb-4">
<CheckCircle className="w-4 h-4 text-green-600" />
<span className="text-sm font-medium text-green-700 capitalize">
{downloadingModel.status}
</span>
</div>
)}
{/* Status Message */}
{downloadingModel.status && downloadingModel.status !== "pulled" && (
<div className="text-xs text-gray-500">
{downloadingModel.status === "downloading" && "Downloading model files..."}
{downloadingModel.status === "verifying" && "Verifying model integrity..."}
{downloadingModel.status === "pulling" && "Pulling model from registry..."}
</div>
)}
{/* Download Info */}
{downloadingModel.downloaded && downloadingModel.size && (
<div className="mt-4 p-3 bg-gray-50 rounded-lg">
<div className="flex justify-between text-xs text-gray-600">
<span>Downloaded: {(downloadingModel.downloaded / 1024 / 1024).toFixed(1)} MB</span>
<span>Total: {(downloadingModel.size / 1024 / 1024).toFixed(1)} MB</span>
</div>
</div>
)}
</div>
</div>
</div>
</Wrapper>
)}
</div>
);
};