import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle, } from "@/components/ui/card"; import { giteaApi } from "@/lib/api"; import type { GiteaConfig, MirrorStrategy } from "@/types/config"; import { toast } from "sonner"; import { OrganizationStrategy } from "./OrganizationStrategy"; import { OrganizationConfiguration } from "./OrganizationConfiguration"; import { Separator } from "../ui/separator"; interface GiteaConfigFormProps { config: GiteaConfig; setConfig: React.Dispatch>; onAutoSave?: (giteaConfig: GiteaConfig) => Promise; isAutoSaving?: boolean; githubUsername?: string; } export function GiteaConfigForm({ config, setConfig, onAutoSave, isAutoSaving, githubUsername }: GiteaConfigFormProps) { const [isLoading, setIsLoading] = useState(false); // Derive the mirror strategy from existing config for backward compatibility const getMirrorStrategy = (): MirrorStrategy => { if (config.mirrorStrategy) return config.mirrorStrategy; if (config.preserveOrgStructure) return "preserve"; if (config.organization && config.organization !== config.username) return "single-org"; return "flat-user"; }; const [mirrorStrategy, setMirrorStrategy] = useState(getMirrorStrategy()); // Update config when strategy changes useEffect(() => { const newConfig = { ...config }; switch (mirrorStrategy) { case "preserve": newConfig.preserveOrgStructure = true; newConfig.mirrorStrategy = "preserve"; break; case "single-org": newConfig.preserveOrgStructure = false; newConfig.mirrorStrategy = "single-org"; if (!newConfig.organization) { newConfig.organization = "github-mirrors"; } break; case "flat-user": newConfig.preserveOrgStructure = false; newConfig.mirrorStrategy = "flat-user"; newConfig.organization = ""; break; } setConfig(newConfig); if (onAutoSave) { onAutoSave(newConfig); } }, [mirrorStrategy]); const handleChange = ( e: React.ChangeEvent ) => { const { name, value, type } = e.target; const checked = type === "checkbox" ? (e.target as HTMLInputElement).checked : undefined; // Special handling for preserveOrgStructure changes if ( name === "preserveOrgStructure" && config.preserveOrgStructure !== checked ) { toast.info( "Changing this setting may affect how repositories are accessed in Gitea. " + "Existing mirrored repositories will still be accessible during sync operations.", { duration: 6000, position: "top-center", } ); } const newConfig = { ...config, [name]: type === "checkbox" ? checked : value, }; setConfig(newConfig); // Auto-save for all field changes if (onAutoSave) { onAutoSave(newConfig); } }; const testConnection = async () => { if (!config.url || !config.token) { toast.error("Gitea URL and token are required to test the connection"); return; } setIsLoading(true); try { const result = await giteaApi.testConnection(config.url, config.token); if (result.success) { toast.success("Successfully connected to Gitea!"); } else { toast.error( "Failed to connect to Gitea. Please check your URL and token." ); } } catch (error) { toast.error( error instanceof Error ? error.message : "An unknown error occurred" ); } finally { setIsLoading(false); } }; return ( Gitea Configuration

Create a token in your Gitea instance under Settings > Applications.

{ const newConfig = { ...config, organization: org }; setConfig(newConfig); if (onAutoSave) onAutoSave(newConfig); }} onStarredReposOrgChange={(org) => { const newConfig = { ...config, starredReposOrg: org }; setConfig(newConfig); if (onAutoSave) onAutoSave(newConfig); }} onVisibilityChange={(visibility) => { const newConfig = { ...config, visibility }; setConfig(newConfig); if (onAutoSave) onAutoSave(newConfig); }} />
); }