SSOMetadata.tsx 3.8 KB

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