blob: ab3e6c92c2c0cb7c31cd35d1d307657050015247 [file] [log] [blame]
gio7f98e772025-05-07 11:00:14 +00001import { useProjectId, useGithubService, useStateStore } from '@/lib/state';
2import { Form, FormControl, FormField, FormItem, FormMessage } from './components/ui/form';
3import { Input } from './components/ui/input';
4import { useForm } from 'react-hook-form';
5import { z } from 'zod';
6import { zodResolver } from '@hookform/resolvers/zod';
7import { Button } from './components/ui/button';
8import { useToast } from '@/hooks/use-toast';
9import { Checkbox } from './components/ui/checkbox';
10import { useState, useCallback } from 'react';
11
12const schema = z.object({
13 githubToken: z.string().min(1, "GitHub token is required"),
14});
15
16export function Integrations() {
17 const { toast } = useToast();
18 const store = useStateStore();
19 const projectId = useProjectId();
20 const [isEditing, setIsEditing] = useState(false);
21 const githubService = useGithubService();
22 const [isSaving, setIsSaving] = useState(false);
23
24 const form = useForm<z.infer<typeof schema>>({
25 resolver: zodResolver(schema),
26 mode: "onChange",
27 });
28
29 const onSubmit = useCallback(async (data: z.infer<typeof schema>) => {
30 if (!projectId) return;
31
32 setIsSaving(true);
33
34 try {
35 const response = await fetch(`/api/project/${projectId}/github-token`, {
36 method: "POST",
37 headers: {
38 "Content-Type": "application/json",
39 },
40 body: JSON.stringify({ githubToken: data.githubToken }),
41 });
42
43 if (!response.ok) {
44 throw new Error("Failed to save GitHub token");
45 }
46
47 await store.refreshEnv();
48 setIsEditing(false);
49 form.reset();
50 toast({
51 title: "GitHub token saved successfully",
52 });
53 } catch (error) {
54 toast({
55 variant: "destructive",
56 title: "Failed to save GitHub token",
57 description: error instanceof Error ? error.message : "Unknown error",
58 });
59 } finally {
60 setIsSaving(false);
61 }
62 }, [projectId, store, form, toast, setIsEditing, setIsSaving]);
63
64 const handleCancel = () => {
65 setIsEditing(false);
66 form.reset();
67 };
68
69 return (
gioa2a845c2025-05-08 11:27:14 +000070 <div className="px-5 space-y-6">
gio7f98e772025-05-07 11:00:14 +000071 <div>
72 <h3 className="text-md font-medium mb-2">GitHub</h3>
73 <div className="space-y-4">
74 <div className="flex items-center space-x-2">
75 <Checkbox checked={!!githubService} disabled />
76 <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
77 GitHub Access Token
78 </label>
79 </div>
80
81 {!!githubService && !isEditing && (
82 <Button
83 variant="outline"
84 onClick={() => setIsEditing(true)}
85 >
86 Update Access Token
87 </Button>
88 )}
89
gio6cf8c272025-05-08 09:01:38 +000090 {(!githubService || isEditing) && (
gio7f98e772025-05-07 11:00:14 +000091 <Form {...form}>
92 <form className="space-y-4" onSubmit={form.handleSubmit(onSubmit)}>
93 <FormField
94 control={form.control}
95 name="githubToken"
96 render={({ field }) => (
97 <FormItem>
98 <FormControl>
99 <Input
100 type="password"
101 placeholder="GitHub Personal Access Token"
102 className="border border-black"
103 {...field}
104 />
105 </FormControl>
106 <FormMessage />
107 </FormItem>
108 )}
109 />
110 <div className="flex space-x-2">
111 <Button type="submit" disabled={isSaving}>
112 {isSaving ? "Saving..." : "Save"}
113 </Button>
114 {!!githubService && (
115 <Button
116 type="button"
117 variant="outline"
118 onClick={handleCancel}
119 disabled={isSaving}
120 >
121 Cancel
122 </Button>
123 )}
124 </div>
125 </form>
126 </Form>
127 )}
128 </div>
129 </div>
130 </div>
131 );
132}