| import { useProjectId, useGithubService, useStateStore } from "@/lib/state"; |
| import { Form, FormControl, FormField, FormItem, FormMessage } from "./components/ui/form"; |
| import { Input } from "./components/ui/input"; |
| import { useForm } from "react-hook-form"; |
| import { z } from "zod"; |
| import { zodResolver } from "@hookform/resolvers/zod"; |
| import { Button } from "./components/ui/button"; |
| import { useToast } from "@/hooks/use-toast"; |
| import { Checkbox } from "./components/ui/checkbox"; |
| import { useState, useCallback } from "react"; |
| |
| const schema = z.object({ |
| githubToken: z.string().min(1, "GitHub token is required"), |
| }); |
| |
| export function Integrations() { |
| const { toast } = useToast(); |
| const store = useStateStore(); |
| const projectId = useProjectId(); |
| const [isEditing, setIsEditing] = useState(false); |
| const githubService = useGithubService(); |
| const [isSaving, setIsSaving] = useState(false); |
| |
| const form = useForm<z.infer<typeof schema>>({ |
| resolver: zodResolver(schema), |
| mode: "onChange", |
| }); |
| |
| const onSubmit = useCallback( |
| async (data: z.infer<typeof schema>) => { |
| if (!projectId) return; |
| |
| setIsSaving(true); |
| |
| try { |
| const response = await fetch(`/api/project/${projectId}/github-token`, { |
| method: "POST", |
| headers: { |
| "Content-Type": "application/json", |
| }, |
| body: JSON.stringify({ githubToken: data.githubToken }), |
| }); |
| |
| if (!response.ok) { |
| throw new Error("Failed to save GitHub token"); |
| } |
| |
| await store.refreshEnv(); |
| setIsEditing(false); |
| form.reset(); |
| toast({ |
| title: "GitHub token saved successfully", |
| }); |
| } catch (error) { |
| toast({ |
| variant: "destructive", |
| title: "Failed to save GitHub token", |
| description: error instanceof Error ? error.message : "Unknown error", |
| }); |
| } finally { |
| setIsSaving(false); |
| } |
| }, |
| [projectId, store, form, toast, setIsEditing, setIsSaving], |
| ); |
| |
| const handleCancel = () => { |
| setIsEditing(false); |
| form.reset(); |
| }; |
| |
| return ( |
| <div className="px-5 space-y-6"> |
| <div> |
| <div className="flex items-center space-x-2"> |
| <Checkbox checked={!!githubService} disabled /> |
| <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"> |
| <h3 className="text-md font-medium mb-2">GitHub</h3> |
| </label> |
| </div> |
| |
| {!!githubService && !isEditing && ( |
| <Button variant="outline" onClick={() => setIsEditing(true)}> |
| Update Access Token |
| </Button> |
| )} |
| |
| {(!githubService || isEditing) && ( |
| <Form {...form}> |
| <form className="space-y-4" onSubmit={form.handleSubmit(onSubmit)}> |
| <FormField |
| control={form.control} |
| name="githubToken" |
| render={({ field }) => ( |
| <FormItem> |
| <FormControl> |
| <Input |
| type="password" |
| placeholder="GitHub Personal Access Token" |
| className="border border-black" |
| {...field} |
| /> |
| </FormControl> |
| <FormMessage /> |
| </FormItem> |
| )} |
| /> |
| <div className="flex space-x-2"> |
| <Button type="submit" disabled={isSaving}> |
| {isSaving ? "Saving..." : "Save"} |
| </Button> |
| {!!githubService && ( |
| <Button type="button" variant="outline" onClick={handleCancel} disabled={isSaving}> |
| Cancel |
| </Button> |
| )} |
| </div> |
| </form> |
| </Form> |
| )} |
| </div> |
| </div> |
| ); |
| } |