mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-03-31 10:08:15 +03:00
170 lines
6.9 KiB
TypeScript
170 lines
6.9 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Button } from './ui/button';
|
|
import { Copy, Check, Terminal, Container, Cloud } from 'lucide-react';
|
|
|
|
type InstallMethod = 'docker' | 'manual' | 'proxmox';
|
|
|
|
export function Installation() {
|
|
const [activeMethod, setActiveMethod] = useState<InstallMethod>('docker');
|
|
const [copiedCommand, setCopiedCommand] = useState<string | null>(null);
|
|
|
|
const copyToClipboard = async (text: string, commandId: string) => {
|
|
await navigator.clipboard.writeText(text);
|
|
setCopiedCommand(commandId);
|
|
setTimeout(() => setCopiedCommand(null), 2000);
|
|
};
|
|
|
|
const installMethods = {
|
|
docker: {
|
|
icon: Container,
|
|
title: "Docker",
|
|
description: "Recommended for most users",
|
|
steps: [
|
|
{
|
|
title: "Clone the repository",
|
|
command: "git clone https://github.com/RayLabsHQ/gitea-mirror.git && cd gitea-mirror",
|
|
id: "docker-clone"
|
|
},
|
|
{
|
|
title: "Start with Docker Compose",
|
|
command: "docker compose -f docker-compose.alt.yml up -d",
|
|
id: "docker-start"
|
|
},
|
|
{
|
|
title: "Access the application",
|
|
command: "# Open http://localhost:4321 in your browser",
|
|
id: "docker-access"
|
|
}
|
|
]
|
|
},
|
|
manual: {
|
|
icon: Terminal,
|
|
title: "Manual",
|
|
description: "For development or custom setups",
|
|
steps: [
|
|
{
|
|
title: "Install Bun runtime",
|
|
command: "curl -fsSL https://bun.sh/install | bash",
|
|
id: "manual-bun"
|
|
},
|
|
{
|
|
title: "Clone and setup",
|
|
command: "git clone https://github.com/RayLabsHQ/gitea-mirror.git\ncd gitea-mirror\nbun run setup",
|
|
id: "manual-setup"
|
|
},
|
|
{
|
|
title: "Start the application",
|
|
command: "bun run dev",
|
|
id: "manual-start"
|
|
}
|
|
]
|
|
},
|
|
proxmox: {
|
|
icon: Cloud,
|
|
title: "Proxmox LXC",
|
|
description: "One-click install for Proxmox VE",
|
|
steps: [
|
|
{
|
|
title: "Run the installation script",
|
|
command: 'bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/gitea-mirror.sh)"',
|
|
id: "proxmox-install"
|
|
},
|
|
{
|
|
title: "Follow the prompts",
|
|
command: "# The script will guide you through the setup",
|
|
id: "proxmox-follow"
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section id="installation" className="py-16 sm:py-24 px-4 sm:px-6 lg:px-8">
|
|
<div className="max-w-4xl mx-auto">
|
|
<div className="text-center mb-8 sm:mb-16">
|
|
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight">
|
|
Get Started in Minutes
|
|
</h2>
|
|
<p className="mt-4 text-base sm:text-lg text-muted-foreground">
|
|
Choose your preferred installation method
|
|
</p>
|
|
</div>
|
|
|
|
{/* Installation method tabs */}
|
|
<div className="flex flex-col sm:flex-row flex-wrap justify-center gap-3 sm:gap-4 mb-8 sm:mb-12">
|
|
{(Object.entries(installMethods) as [InstallMethod, typeof installMethods[InstallMethod]][]).map(([method, config]) => {
|
|
const Icon = config.icon;
|
|
return (
|
|
<button
|
|
key={method}
|
|
onClick={() => setActiveMethod(method)}
|
|
className={`flex items-center gap-3 px-4 sm:px-6 py-3 rounded-lg border transition-all min-h-[60px] ${
|
|
activeMethod === method
|
|
? 'bg-gradient-to-r from-primary to-accent text-primary-foreground border-transparent shadow-lg shadow-primary/25'
|
|
: 'bg-card hover:bg-muted border-border hover:border-primary/30'
|
|
}`}
|
|
>
|
|
<Icon className="w-5 h-5 flex-shrink-0" />
|
|
<div className="text-left">
|
|
<p className="font-semibold text-sm sm:text-base">{config.title}</p>
|
|
<p className={`text-xs ${activeMethod === method ? 'text-primary-foreground/80' : 'text-muted-foreground'}`}>
|
|
{config.description}
|
|
</p>
|
|
</div>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
{/* Installation steps */}
|
|
<div className="space-y-4 sm:space-y-6">
|
|
{installMethods[activeMethod].steps.map((step, index) => (
|
|
<div key={step.id} className="relative">
|
|
<div className="flex items-start gap-3 sm:gap-4">
|
|
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-gradient-to-br from-primary to-accent flex items-center justify-center shadow-md shadow-primary/20">
|
|
<span className="text-sm font-semibold text-primary-foreground">{index + 1}</span>
|
|
</div>
|
|
<div className="flex-grow min-w-0">
|
|
<h3 className="font-semibold mb-2 text-sm sm:text-base">{step.title}</h3>
|
|
<div className="relative group">
|
|
<div className="relative overflow-hidden rounded-lg">
|
|
<pre className="bg-muted/50 p-3 sm:p-4 pr-10 sm:pr-12 overflow-x-auto text-[11px] sm:text-sm font-mono scrollbar-thin scrollbar-thumb-muted-foreground/20 scrollbar-track-transparent">
|
|
<code className="block whitespace-nowrap">{step.command}</code>
|
|
</pre>
|
|
{/* Scroll indicator gradient for mobile */}
|
|
<div className="absolute inset-y-0 right-0 w-8 bg-gradient-to-l from-muted/50 to-transparent pointer-events-none sm:hidden" />
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="absolute top-1 right-1 sm:top-2 sm:right-2 w-7 h-7 sm:w-9 sm:h-9 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity z-10"
|
|
onClick={() => copyToClipboard(step.command, step.id)}
|
|
>
|
|
{copiedCommand === step.id ? (
|
|
<Check className="h-3 w-3 sm:h-4 sm:w-4 text-green-600" />
|
|
) : (
|
|
<Copy className="h-3 w-3 sm:h-4 sm:w-4" />
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{index < installMethods[activeMethod].steps.length - 1 && (
|
|
<div className="absolute left-4 top-10 bottom-0 w-[1px] bg-border -z-10" />
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Additional info */}
|
|
<div className="mt-8 sm:mt-12 p-4 sm:p-6 rounded-lg bg-muted/30 border">
|
|
<p className="text-xs sm:text-sm text-muted-foreground">
|
|
<strong className="text-foreground">First user becomes admin.</strong> After installation,
|
|
create your account and configure GitHub and Gitea connections through the web interface.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|