@@ -2,6 +2,7 @@ import type { Field, FieldType, SchemaEntity } from "@dafthunk/types";
22import Asterisk from "lucide-react/icons/asterisk" ;
33import Hash from "lucide-react/icons/hash" ;
44import KeyRound from "lucide-react/icons/key-round" ;
5+ import Link from "lucide-react/icons/link" ;
56import PlusCircle from "lucide-react/icons/plus-circle" ;
67import Trash2 from "lucide-react/icons/trash-2" ;
78import { useEffect , useState } from "react" ;
@@ -16,6 +17,11 @@ import {
1617} from "@/components/ui/dialog" ;
1718import { Input } from "@/components/ui/input" ;
1819import { Label } from "@/components/ui/label" ;
20+ import {
21+ Popover ,
22+ PopoverContent ,
23+ PopoverTrigger ,
24+ } from "@/components/ui/popover" ;
1925import {
2026 Select ,
2127 SelectContent ,
@@ -45,9 +51,10 @@ const FIELD_TYPES: FieldType[] = [
4551interface FieldEditorProps {
4652 fields : Field [ ] ;
4753 onChange : ( fields : Field [ ] ) => void ;
54+ schemas ?: SchemaEntity [ ] ;
4855}
4956
50- function FieldEditor ( { fields, onChange } : FieldEditorProps ) {
57+ function FieldEditor ( { fields, onChange, schemas } : FieldEditorProps ) {
5158 const addField = ( ) => {
5259 onChange ( [ ...fields , { name : "" , type : "string" } ] ) ;
5360 } ;
@@ -91,9 +98,7 @@ function FieldEditor({ fields, onChange }: FieldEditorProps) {
9198 < Input
9299 placeholder = "Name"
93100 value = { field . name }
94- onChange = { ( e ) =>
95- updateField ( index , { name : e . target . value } )
96- }
101+ onChange = { ( e ) => updateField ( index , { name : e . target . value } ) }
97102 className = { cn (
98103 "flex-1 min-w-0" ,
99104 isDuplicate && "border-destructive"
@@ -151,8 +156,7 @@ function FieldEditor({ fields, onChange }: FieldEditorProps) {
151156 onChange (
152157 fields . map ( ( f , i ) => ( {
153158 ...f ,
154- primaryKey :
155- i === index ? true : undefined ,
159+ primaryKey : i === index ? true : undefined ,
156160 } ) )
157161 ) ;
158162 }
@@ -201,9 +205,7 @@ function FieldEditor({ fields, onChange }: FieldEditorProps) {
201205 </ Button >
202206 </ TooltipTrigger >
203207 < TooltipContent >
204- { field . unique
205- ? "Remove unique constraint"
206- : "Set as unique" }
208+ { field . unique ? "Remove unique constraint" : "Set as unique" }
207209 </ TooltipContent >
208210 </ Tooltip >
209211 </ TooltipProvider >
@@ -232,12 +234,73 @@ function FieldEditor({ fields, onChange }: FieldEditorProps) {
232234 </ Button >
233235 </ TooltipTrigger >
234236 < TooltipContent >
235- { field . required
236- ? "Set as optional"
237- : "Set as required" }
237+ { field . required ? "Set as optional" : "Set as required" }
238238 </ TooltipContent >
239239 </ Tooltip >
240240 </ TooltipProvider >
241+ { schemas && schemas . length > 0 && (
242+ < Popover >
243+ < TooltipProvider >
244+ < Tooltip >
245+ < TooltipTrigger asChild >
246+ < PopoverTrigger asChild >
247+ < Button
248+ type = "button"
249+ variant = { field . references ? "secondary" : "ghost" }
250+ size = "icon"
251+ className = "h-8 w-8 shrink-0"
252+ >
253+ < Link
254+ className = { cn (
255+ "h-4 w-4" ,
256+ field . references
257+ ? "text-foreground"
258+ : "text-muted-foreground"
259+ ) }
260+ />
261+ </ Button >
262+ </ PopoverTrigger >
263+ </ TooltipTrigger >
264+ < TooltipContent >
265+ { field . references
266+ ? `References ${ field . references } `
267+ : "Set foreign key reference" }
268+ </ TooltipContent >
269+ </ Tooltip >
270+ </ TooltipProvider >
271+ < PopoverContent className = "w-40 p-1" align = "start" >
272+ < button
273+ type = "button"
274+ className = { cn (
275+ "w-full rounded-sm px-2 py-1.5 text-sm text-left hover:bg-accent" ,
276+ ! field . references && "font-medium"
277+ ) }
278+ onClick = { ( ) =>
279+ updateField ( index , { references : undefined } )
280+ }
281+ >
282+ None
283+ </ button >
284+ { schemas
285+ . filter ( ( s ) => s . fields . some ( ( f ) => f . primaryKey ) )
286+ . map ( ( s ) => (
287+ < button
288+ key = { s . id }
289+ type = "button"
290+ className = { cn (
291+ "w-full rounded-sm px-2 py-1.5 text-sm text-left hover:bg-accent" ,
292+ field . references === s . name && "font-medium"
293+ ) }
294+ onClick = { ( ) =>
295+ updateField ( index , { references : s . name } )
296+ }
297+ >
298+ { s . name }
299+ </ button >
300+ ) ) }
301+ </ PopoverContent >
302+ </ Popover >
303+ ) }
241304 < Button
242305 type = "button"
243306 variant = "ghost"
@@ -258,6 +321,7 @@ export interface SchemaDialogProps {
258321 open : boolean ;
259322 onOpenChange : ( open : boolean ) => void ;
260323 schema ?: SchemaEntity | null ;
324+ schemas ?: SchemaEntity [ ] ;
261325 onSubmit : ( data : {
262326 name : string ;
263327 description : string ;
@@ -271,6 +335,7 @@ export function SchemaDialog({
271335 open,
272336 onOpenChange,
273337 schema,
338+ schemas,
274339 onSubmit,
275340 title,
276341 submitLabel,
@@ -336,7 +401,7 @@ export function SchemaDialog({
336401 rows = { 2 }
337402 />
338403 </ div >
339- < FieldEditor fields = { fields } onChange = { setFields } />
404+ < FieldEditor fields = { fields } onChange = { setFields } schemas = { schemas } />
340405 < DialogFooter >
341406 < Button
342407 variant = "outline"
0 commit comments