refactor(settings): enhance project handling in SettingsView

- Introduce type conversion for ElectronProject to SettingsProject
- Update effective theme calculation to use converted settingsProject
- Refactor currentProject references to use settingsProject in Appearance and DangerZone sections
- Improve type safety and maintainability in settings-view.tsx
This commit is contained in:
Kacper
2025-12-11 01:00:42 +01:00
parent ac3ea90950
commit 82cc8abd29
2 changed files with 166 additions and 3 deletions

View File

@@ -18,6 +18,8 @@ import { KanbanDisplaySection } from "./settings-view/kanban-display/kanban-disp
import { KeyboardShortcutsSection } from "./settings-view/keyboard-shortcuts/keyboard-shortcuts-section";
import { FeatureDefaultsSection } from "./settings-view/feature-defaults/feature-defaults-section";
import { DangerZoneSection } from "./settings-view/danger-zone/danger-zone-section";
import type { Project as SettingsProject, Theme } from "./settings-view/shared/types";
import type { Project as ElectronProject } from "@/lib/electron";
export function SettingsView() {
const {
@@ -37,8 +39,21 @@ export function SettingsView() {
moveProjectToTrash,
} = useAppStore();
// Convert electron Project to settings-view Project type
const convertProject = (project: ElectronProject | null): SettingsProject | null => {
if (!project) return null;
return {
id: project.id,
name: project.name,
path: project.path,
theme: project.theme as Theme | undefined,
};
};
const settingsProject = convertProject(currentProject);
// Compute the effective theme for the current project
const effectiveTheme = currentProject?.theme || theme;
const effectiveTheme = (settingsProject?.theme || theme) as Theme;
// Handler to set theme - saves to project if one is selected, otherwise to global
const handleSetTheme = (newTheme: typeof theme) => {
@@ -111,7 +126,7 @@ export function SettingsView() {
{/* Appearance Section */}
<AppearanceSection
effectiveTheme={effectiveTheme}
currentProject={currentProject}
currentProject={settingsProject}
onThemeChange={handleSetTheme}
/>
@@ -138,7 +153,7 @@ export function SettingsView() {
{/* Danger Zone Section - Only show when a project is selected */}
<DangerZoneSection
project={currentProject}
project={settingsProject}
onDeleteClick={() => setShowDeleteDialog(true)}
/>

View File

@@ -0,0 +1,148 @@
import type { Dispatch, SetStateAction } from "react";
import type { ApiKeys } from "@/store/app-store";
export type ProviderKey = "anthropic" | "google" | "openai";
export interface ProviderConfig {
key: ProviderKey;
label: string;
inputId: string;
placeholder: string;
value: string;
setValue: Dispatch<SetStateAction<string>>;
showValue: boolean;
setShowValue: Dispatch<SetStateAction<boolean>>;
hasStoredKey: string | null | undefined;
inputTestId: string;
toggleTestId: string;
testButton: {
onClick: () => Promise<void> | void;
disabled: boolean;
loading: boolean;
testId: string;
};
result: { success: boolean; message: string } | null;
resultTestId: string;
resultMessageTestId: string;
descriptionPrefix: string;
descriptionLinkHref: string;
descriptionLinkText: string;
descriptionSuffix?: string;
}
export interface ProviderConfigParams {
apiKeys: ApiKeys;
anthropic: {
value: string;
setValue: Dispatch<SetStateAction<string>>;
show: boolean;
setShow: Dispatch<SetStateAction<boolean>>;
testing: boolean;
onTest: () => Promise<void>;
result: { success: boolean; message: string } | null;
};
google: {
value: string;
setValue: Dispatch<SetStateAction<string>>;
show: boolean;
setShow: Dispatch<SetStateAction<boolean>>;
testing: boolean;
onTest: () => Promise<void>;
result: { success: boolean; message: string } | null;
};
openai: {
value: string;
setValue: Dispatch<SetStateAction<string>>;
show: boolean;
setShow: Dispatch<SetStateAction<boolean>>;
testing: boolean;
onTest: () => Promise<void>;
result: { success: boolean; message: string } | null;
};
}
export const buildProviderConfigs = ({
apiKeys,
anthropic,
google,
openai,
}: ProviderConfigParams): ProviderConfig[] => [
{
key: "anthropic",
label: "Anthropic API Key (Claude)",
inputId: "anthropic-key",
placeholder: "sk-ant-...",
value: anthropic.value,
setValue: anthropic.setValue,
showValue: anthropic.show,
setShowValue: anthropic.setShow,
hasStoredKey: apiKeys.anthropic,
inputTestId: "anthropic-api-key-input",
toggleTestId: "toggle-anthropic-visibility",
testButton: {
onClick: anthropic.onTest,
disabled: !anthropic.value || anthropic.testing,
loading: anthropic.testing,
testId: "test-claude-connection",
},
result: anthropic.result,
resultTestId: "test-connection-result",
resultMessageTestId: "test-connection-message",
descriptionPrefix: "Used for Claude AI features. Get your key at",
descriptionLinkHref: "https://console.anthropic.com/account/keys",
descriptionLinkText: "console.anthropic.com",
descriptionSuffix:
". Alternatively, the CLAUDE_CODE_OAUTH_TOKEN environment variable can be used.",
},
{
key: "google",
label: "Google API Key (Gemini)",
inputId: "google-key",
placeholder: "AIza...",
value: google.value,
setValue: google.setValue,
showValue: google.show,
setShowValue: google.setShow,
hasStoredKey: apiKeys.google,
inputTestId: "google-api-key-input",
toggleTestId: "toggle-google-visibility",
testButton: {
onClick: google.onTest,
disabled: !google.value || google.testing,
loading: google.testing,
testId: "test-gemini-connection",
},
result: google.result,
resultTestId: "gemini-test-connection-result",
resultMessageTestId: "gemini-test-connection-message",
descriptionPrefix:
"Used for Gemini AI features (including image/design prompts). Get your key at",
descriptionLinkHref: "https://makersuite.google.com/app/apikey",
descriptionLinkText: "makersuite.google.com",
},
{
key: "openai",
label: "OpenAI API Key (Codex/GPT)",
inputId: "openai-key",
placeholder: "sk-...",
value: openai.value,
setValue: openai.setValue,
showValue: openai.show,
setShowValue: openai.setShow,
hasStoredKey: apiKeys.openai,
inputTestId: "openai-api-key-input",
toggleTestId: "toggle-openai-visibility",
testButton: {
onClick: openai.onTest,
disabled: !openai.value || openai.testing,
loading: openai.testing,
testId: "test-openai-connection",
},
result: openai.result,
resultTestId: "openai-test-connection-result",
resultMessageTestId: "openai-test-connection-message",
descriptionPrefix: "Used for OpenAI Codex CLI and GPT models. Get your key at",
descriptionLinkHref: "https://platform.openai.com/api-keys",
descriptionLinkText: "platform.openai.com",
},
];