SSOMetadata.tsx129 lines · main
1import { Upload } from 'lucide-react'
2import { useEffect, useRef, useState } from 'react'
3import { useForm } from 'react-hook-form'
4import {
5 Button,
6 FormControl,
7 FormField,
8 FormItem,
9 FormMessage,
10 Input,
11 Tabs_Shadcn_,
12 TabsContent_Shadcn_,
13 TabsList_Shadcn_,
14 TabsTrigger_Shadcn_,
15} from 'ui'
16import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
17
18import { SSOConfigFormSchema } from './SSOConfig'
19
20export const SSOMetadata = ({
21 form,
22}: {
23 form: ReturnType<typeof useForm<SSOConfigFormSchema>>
24}) => {
25 const fileInputRef = useRef<HTMLInputElement>(null)
26 const [fileName, setFileName] = useState<string | null>(null)
27 const [tab, setTab] = useState<'url' | 'file'>('url')
28
29 useEffect(() => {
30 if (form.getValues('metadataXmlFile')) {
31 setTab('file')
32 } else if (form.getValues('metadataXmlUrl')) {
33 setTab('url')
34 }
35 }, [form])
36
37 const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
38 form.clearErrors('metadataXmlFile')
39 const file = e.target.files?.[0]
40 if (!file) return
41 if (!file.name.endsWith('.xml')) {
42 form.setError('metadataXmlFile', {
43 type: 'manual',
44 message: 'Please upload a valid .xml file',
45 })
46 return
47 }
48 try {
49 const text = await file.text()
50 form.setValue('metadataXmlFile', text, { shouldDirty: true })
51 setFileName(file.name)
52 } catch (err) {
53 form.setError('metadataXmlFile', {
54 type: 'manual',
55 message: 'Failed to read file',
56 })
57 }
58 }
59
60 return (
61 <FormItemLayout
62 label="Metadata"
63 layout="flex-row-reverse"
64 description="Provide a link to your metadata .xml file or upload one"
65 className="gap-1"
66 >
67 <div className=" w-96">
68 <Tabs_Shadcn_
69 value={tab}
70 onValueChange={(value: string) => setTab(value as 'url' | 'file')}
71 className="max-w-2xl"
72 >
73 <TabsList_Shadcn_ className="mx-auto gap-5 w-auto">
74 <TabsTrigger_Shadcn_ className=" " value="url">
75 URL
76 </TabsTrigger_Shadcn_>
77 <TabsTrigger_Shadcn_ className=" " value="file">
78 Upload file
79 </TabsTrigger_Shadcn_>
80 </TabsList_Shadcn_>
81 <TabsContent_Shadcn_ value="url">
82 <FormField
83 name="metadataXmlUrl"
84 render={({ field }) => (
85 <FormItem>
86 <FormControl>
87 <Input
88 {...field}
89 placeholder="https://example.com/metadata.xml"
90 autoComplete="off"
91 />
92 </FormControl>
93 <FormMessage />
94 </FormItem>
95 )}
96 />
97 </TabsContent_Shadcn_>
98 <TabsContent_Shadcn_ value="file">
99 <FormField
100 name="metadataXmlUrl"
101 render={() => (
102 <div className="flex flex-col gap-2 max-w-md">
103 <div className="flex items-center gap-2">
104 <input
105 ref={fileInputRef}
106 type="file"
107 accept=".xml"
108 className="hidden"
109 onChange={handleFileChange}
110 />
111 <Button
112 type="default"
113 icon={<Upload className="w-4 h-4" />}
114 onClick={() => fileInputRef.current?.click()}
115 >
116 Upload XML
117 </Button>
118 {fileName && <span className="text-xs text-foreground-light">{fileName}</span>}
119 </div>
120 <FormMessage />
121 </div>
122 )}
123 />
124 </TabsContent_Shadcn_>
125 </Tabs_Shadcn_>
126 </div>
127 </FormItemLayout>
128 )
129}