'use client'
import { useState } from 'react'
import { supabase } from '@/lib/supabase'
import { IoArrowBackOutline, IoLogoGithub, IoLockClosedOutline, IoGlobeOutline } from 'react-icons/io5'
interface GitHubCreateRepoProps {
bookId: string
accessToken: string
githubUsername: string
onBack: () => void
onCreate: () => void
}
export default function GitHubCreateRepo({
bookId,
accessToken,
githubUsername,
onBack,
onCreate
}: GitHubCreateRepoProps) {
const [repoName, setRepoName] = useState('')
const [description, setDescription] = useState('')
const [isPrivate, setIsPrivate] = useState(true)
const [isCreating, setIsCreating] = useState(false)
const [error, setError] = useState<string | null>(null)
const handleCreateRepository = async (e: React.FormEvent) => {
e.preventDefault()
if (!repoName.trim() || !accessToken || !bookId) return
setIsCreating(true)
setError(null)
try {
// Create repository via GitHub API
const response = await fetch('https://api.github.com/user/repos', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: repoName,
description: description || undefined,
private: isPrivate,
auto_init: true // Initialize with README to avoid empty repo issues
}),
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || 'Failed to create repository')
}
const newRepo = await response.json()
// Get current user
const { data: { user } } = await supabase.auth.getUser()
if (!user) {
throw new Error('Please log in first')
}
// Create GitHub integration
const integration = {
provider: 'github',
repository_url: newRepo.html_url,
repository_name: newRepo.name,
repository_full_name: newRepo.full_name,
access_token: accessToken,
github_username: githubUsername,
repository_id: newRepo.id,
is_private: newRepo.private,
user_id: user.id
}
const integrationResponse = await fetch(`/api/books/${bookId}/github-integration`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ integration }),
})
if (!integrationResponse.ok) {
const errorData = await integrationResponse.json()
throw new Error(errorData.error || 'Failed to connect repository')
}
// Success! Call the onCreate callback
onCreate()
} catch (error) {
setError(error instanceof Error ? error.message : 'Failed to create repository')
} finally {
setIsCreating(false)
}
}
return (
<div className="flex flex-col h-full">
{/* Header */}
<div className="p-3 border-b border-slate-700">
<div className="flex items-center gap-2 mb-2">
<button
onClick={onBack}
className="p-1 rounded hover:bg-slate-700 text-slate-400 hover:text-slate-200 transition-colors"
>
<IoArrowBackOutline className="w-4 h-4" />
</button>
<IoLogoGithub className="w-4 h-4 text-green-400" />
<span className="text-sm font-semibold text-slate-200">Create Repository</span>
</div>
<div className="text-xs bg-green-900/20 text-green-400 px-2 py-1 rounded-md inline-block">
@{githubUsername}
</div>
</div>
{/* Form */}
<div className="flex-1 overflow-y-auto p-3">
<form onSubmit={handleCreateRepository} className="space-y-4">
{/* Repository Name */}
<div>
<label htmlFor="repoName" className="block text-xs font-medium text-slate-300 mb-1">
Repository Name *
</label>
<input
type="text"
id="repoName"
value={repoName}
onChange={(e) => setRepoName(e.target.value)}
placeholder="my-awesome-book"
required
className="w-full px-3 py-2 text-xs bg-slate-800 border border-slate-700 rounded-md focus:outline-none focus:ring-1 focus:ring-teal-500 text-slate-200 placeholder-slate-500"
/>
<p className="text-xs text-slate-500 mt-1">
Lowercase letters, numbers, and hyphens only
</p>
</div>
{/* Description */}
<div>
<label htmlFor="description" className="block text-xs font-medium text-slate-300 mb-1">
Description (Optional)
</label>
<textarea
id="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="A brief description..."
rows={2}
className="w-full px-3 py-2 text-xs bg-slate-800 border border-slate-700 rounded-md focus:outline-none focus:ring-1 focus:ring-teal-500 text-slate-200 placeholder-slate-500 resize-none"
/>
</div>
{/* Visibility */}
<div>
<label className="block text-xs font-medium text-slate-300 mb-2">
Visibility
</label>
<div className="space-y-2">
<label className="flex items-center">
<input
type="radio"
value="private"
checked={isPrivate}
onChange={() => setIsPrivate(true)}
className="mr-2 accent-teal-500"
/>
<IoLockClosedOutline className="w-3 h-3 text-yellow-400 mr-1" />
<div className="flex-1">
<div className="text-xs font-medium text-slate-200">Private</div>
<div className="text-xs text-slate-400">Only you can see this</div>
</div>
</label>
<label className="flex items-center">
<input
type="radio"
value="public"
checked={!isPrivate}
onChange={() => setIsPrivate(false)}
className="mr-2 accent-teal-500"
/>
<IoGlobeOutline className="w-3 h-3 text-green-400 mr-1" />
<div className="flex-1">
<div className="text-xs font-medium text-slate-200">Public</div>
<div className="text-xs text-slate-400">Anyone can see this</div>
</div>
</label>
</div>
</div>
{/* Error Display */}
{error && (
<div className="bg-red-900/20 border border-red-700 rounded-md p-2">
<p className="text-xs text-red-300">{error}</p>
</div>
)}
{/* Submit Button */}
<button
type="submit"
disabled={!repoName.trim() || isCreating}
className={`w-full px-3 py-2 text-xs rounded-md font-medium transition-colors ${
!repoName.trim() || isCreating
? 'bg-slate-700 text-slate-400 cursor-not-allowed'
: 'bg-teal-600 text-white hover:bg-teal-700'
}`}
>
{isCreating ? (
<div className="flex items-center justify-center gap-2">
<div className="animate-spin rounded-full h-3 w-3 border border-slate-400 border-t-transparent"></div>
<span>Creating...</span>
</div>
) : (
'Create Repository'
)}
</button>
</form>
</div>
</div>
)
}