Skip to content

Commit 5a54f14

Browse files
authored
Merge pull request #122 from codegasms/feat/generic-editor-look-update
Two coloumn view for generic-editor.tsx to support datetime fields in right panel
2 parents 9138d3e + 1fdb68e commit 5a54f14

File tree

2 files changed

+185
-81
lines changed

2 files changed

+185
-81
lines changed

components/ui/dialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const DialogContent = React.forwardRef<
3737
<DialogPrimitive.Content
3838
ref={ref}
3939
className={cn(
40-
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
40+
"fixed left-[50%] top-[50%] z-50 grid translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
4141
className,
4242
)}
4343
{...props}

mint/generic-editor.tsx

Lines changed: 184 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -118,97 +118,201 @@ export function GenericEditor<T>({
118118

119119
return (
120120
<Dialog open={isOpen} onOpenChange={onClose}>
121-
<DialogContent className="sm:max-w-[425px]">
121+
<DialogContent
122+
className={`p-8 ${fields.some((f) => f.type === "datetime") ? "w-[1000px]" : "w-[700px]"} rounded-lg`}
123+
>
122124
<DialogHeader>
123125
<DialogTitle>
124126
{data ? `Edit ${title}` : `Add New ${title}`}
125127
</DialogTitle>
126128
</DialogHeader>
127129
<form onSubmit={handleSubmit(onSubmit)}>
128-
<div className="grid gap-4 py-4">
129-
{fields.map((field) => (
130-
<div key={field.name} className="space-y-2">
131-
<Label htmlFor={field.name}>{field.label}</Label>
132-
{field.type === "select" && field.options ? (
133-
<Select
134-
onValueChange={(value) => {
135-
const event = {
136-
target: { name: field.name, value },
137-
};
138-
register(field.name as any).onChange(event);
139-
}}
140-
defaultValue={
141-
data?.[field.name as keyof typeof data] as string
142-
}
143-
>
144-
<SelectTrigger
130+
{fields.some((f) => f.type === "datetime") ? (
131+
<div className="flex gap-0 items-start">
132+
{/* Left panel: non-datetime fields */}
133+
<div className="flex-1 grid gap-4 py-4 pr-6">
134+
{fields
135+
.filter((field) => field.type !== "datetime")
136+
.map((field) => (
137+
<div key={field.name} className="space-y-2">
138+
<Label htmlFor={field.name}>{field.label}</Label>
139+
{field.type === "select" && field.options ? (
140+
<Select
141+
onValueChange={(value) => {
142+
const event = {
143+
target: { name: field.name, value },
144+
};
145+
register(field.name as any).onChange(event);
146+
}}
147+
defaultValue={
148+
data?.[field.name as keyof typeof data] as string
149+
}
150+
>
151+
<SelectTrigger
152+
className={
153+
errors[field.name as keyof typeof errors]
154+
? "border-red-500"
155+
: ""
156+
}
157+
>
158+
<SelectValue
159+
placeholder={
160+
field.placeholder || "Select an option"
161+
}
162+
/>
163+
</SelectTrigger>
164+
<SelectContent>
165+
{field.options.map((option) => (
166+
<SelectItem
167+
key={option.value}
168+
value={option.value}
169+
>
170+
{option.label}
171+
</SelectItem>
172+
))}
173+
</SelectContent>
174+
</Select>
175+
) : field.type === "textarea" ? (
176+
<Textarea
177+
id={field.name}
178+
placeholder={field.placeholder || ""}
179+
{...register(field.name as any)}
180+
className={
181+
errors[field.name as keyof typeof errors]
182+
? "border-red-500"
183+
: ""
184+
}
185+
/>
186+
) : (
187+
<Input
188+
id={field.name}
189+
type={field.type}
190+
placeholder={field.placeholder || ""}
191+
{...register(field.name as any, {
192+
valueAsNumber: field.type === "number",
193+
})}
194+
className={
195+
errors[field.name as keyof typeof errors]
196+
? "border-red-500"
197+
: ""
198+
}
199+
/>
200+
)}
201+
{errors[field.name as keyof typeof errors] && (
202+
<p className="text-red-500 text-sm">
203+
{
204+
errors[field.name as keyof typeof errors]
205+
?.message as string
206+
}
207+
</p>
208+
)}
209+
</div>
210+
))}
211+
</div>
212+
{/* Right panel: datetime fields */}
213+
<div className="w-72 grid gap-4 py-4 pl-6">
214+
{fields
215+
.filter((field) => field.type === "datetime")
216+
.map((field) => (
217+
<div key={field.name} className="space-y-2">
218+
<Label htmlFor={field.name}>{field.label}</Label>
219+
<Input
220+
id={field.name}
221+
type="datetime-local"
222+
placeholder={field.placeholder || ""}
223+
{...register(field.name as any)}
224+
className={
225+
errors[field.name as keyof typeof errors]
226+
? "border-red-500"
227+
: ""
228+
}
229+
/>
230+
{errors[field.name as keyof typeof errors] && (
231+
<p className="text-red-500 text-sm">
232+
{
233+
errors[field.name as keyof typeof errors]
234+
?.message as string
235+
}
236+
</p>
237+
)}
238+
</div>
239+
))}
240+
</div>
241+
</div>
242+
) : (
243+
<div className="grid gap-4 py-4">
244+
{fields.map((field) => (
245+
<div key={field.name} className="space-y-2">
246+
<Label htmlFor={field.name}>{field.label}</Label>
247+
{field.type === "select" && field.options ? (
248+
<Select
249+
onValueChange={(value) => {
250+
const event = {
251+
target: { name: field.name, value },
252+
};
253+
register(field.name as any).onChange(event);
254+
}}
255+
defaultValue={
256+
data?.[field.name as keyof typeof data] as string
257+
}
258+
>
259+
<SelectTrigger
260+
className={
261+
errors[field.name as keyof typeof errors]
262+
? "border-red-500"
263+
: ""
264+
}
265+
>
266+
<SelectValue
267+
placeholder={field.placeholder || "Select an option"}
268+
/>
269+
</SelectTrigger>
270+
<SelectContent>
271+
{field.options.map((option) => (
272+
<SelectItem key={option.value} value={option.value}>
273+
{option.label}
274+
</SelectItem>
275+
))}
276+
</SelectContent>
277+
</Select>
278+
) : field.type === "textarea" ? (
279+
<Textarea
280+
id={field.name}
281+
placeholder={field.placeholder || ""}
282+
{...register(field.name as any)}
145283
className={
146284
errors[field.name as keyof typeof errors]
147285
? "border-red-500"
148286
: ""
149287
}
150-
>
151-
<SelectValue
152-
placeholder={field.placeholder || "Select an option"}
153-
/>
154-
</SelectTrigger>
155-
<SelectContent>
156-
{field.options.map((option) => (
157-
<SelectItem key={option.value} value={option.value}>
158-
{option.label}
159-
</SelectItem>
160-
))}
161-
</SelectContent>
162-
</Select>
163-
) : field.type === "textarea" ? (
164-
<Textarea
165-
id={field.name}
166-
placeholder={field.placeholder || ""}
167-
{...register(field.name as any)}
168-
className={
169-
errors[field.name as keyof typeof errors]
170-
? "border-red-500"
171-
: ""
172-
}
173-
/>
174-
) : field.type === "datetime" ? (
175-
<Input
176-
id={field.name}
177-
type="datetime-local"
178-
placeholder={field.placeholder || ""}
179-
{...register(field.name as any)}
180-
className={
181-
errors[field.name as keyof typeof errors]
182-
? "border-red-500"
183-
: ""
184-
}
185-
/>
186-
) : (
187-
<Input
188-
id={field.name}
189-
type={field.type}
190-
placeholder={field.placeholder || ""}
191-
{...register(field.name as any, {
192-
valueAsNumber: field.type === "number",
193-
})}
194-
className={
195-
errors[field.name as keyof typeof errors]
196-
? "border-red-500"
197-
: ""
198-
}
199-
/>
200-
)}
201-
{errors[field.name as keyof typeof errors] && (
202-
<p className="text-red-500 text-sm">
203-
{
204-
errors[field.name as keyof typeof errors]
205-
?.message as string
206-
}
207-
</p>
208-
)}
209-
</div>
210-
))}
211-
</div>
288+
/>
289+
) : (
290+
<Input
291+
id={field.name}
292+
type={field.type}
293+
placeholder={field.placeholder || ""}
294+
{...register(field.name as any, {
295+
valueAsNumber: field.type === "number",
296+
})}
297+
className={
298+
errors[field.name as keyof typeof errors]
299+
? "border-red-500"
300+
: ""
301+
}
302+
/>
303+
)}
304+
{errors[field.name as keyof typeof errors] && (
305+
<p className="text-red-500 text-sm">
306+
{
307+
errors[field.name as keyof typeof errors]
308+
?.message as string
309+
}
310+
</p>
311+
)}
312+
</div>
313+
))}
314+
</div>
315+
)}
212316
<DialogFooter>
213317
<Button type="submit" disabled={isSaving}>
214318
{isSaving ? (

0 commit comments

Comments
 (0)