Updated forms

This commit is contained in:
2025-06-27 23:19:38 +02:00
parent 1d5dd15d49
commit e69d2aea71
4 changed files with 37 additions and 32 deletions

View File

@@ -23,9 +23,9 @@ function AdvancedUrlForm() {
resolver: zodResolver(advancedUrlSchema), resolver: zodResolver(advancedUrlSchema),
defaultValues: { defaultValues: {
url: "", url: "",
slug: "", slug: null,
title: "", title: null,
maxVisits: 0, maxVisits: null,
expDate: undefined, expDate: undefined,
forwardQueryParams: true, forwardQueryParams: true,
crawlable: false crawlable: false
@@ -71,7 +71,7 @@ function AdvancedUrlForm() {
<FormItem> <FormItem>
<FormLabel>Custom Slug (Optional)</FormLabel> <FormLabel>Custom Slug (Optional)</FormLabel>
<FormControl> <FormControl>
<Input placeholder="my-custom-link" {...field} /> <Input placeholder="my-custom-link" {...field} value={field.value ?? ""} />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
A unique identifier for your short link (max 10 characters). A unique identifier for your short link (max 10 characters).
@@ -133,7 +133,7 @@ function AdvancedUrlForm() {
<FormItem> <FormItem>
<FormLabel>Title (Optional)</FormLabel> <FormLabel>Title (Optional)</FormLabel>
<FormControl> <FormControl>
<Input placeholder="My Link Title" {...field} /> <Input placeholder="My Link Title" {...field} value={field.value ?? ""} />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
A descriptive title for your link (max 100 characters). A descriptive title for your link (max 100 characters).
@@ -153,7 +153,13 @@ function AdvancedUrlForm() {
type="number" type="number"
placeholder="100" placeholder="100"
{...field} {...field}
onChange={(e) => field.onChange(e.target.value ? parseInt(e.target.value) : undefined)} value={field.value ?? ""}
onChange={e =>
field.onChange(
isNaN(e.target.valueAsNumber)
? null
: e.target.valueAsNumber
)}
/> />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
@@ -205,11 +211,11 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) {
defaultValues: { defaultValues: {
url: data.url, url: data.url,
slug: data.slug, slug: data.slug,
title: data.title || "", title: data.title || null,
maxVisits: data.maxVisits || undefined, maxVisits: data.maxVisits || null,
expDate: data.expDate || undefined, expDate: data.expDate || undefined,
forwardQueryParams: data.forwardQueryParams || undefined, forwardQueryParams: data.forwardQueryParams,
crawlable: data.crawlable || undefined crawlable: data.crawlable
} }
}) })
@@ -318,7 +324,7 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) {
<FormItem> <FormItem>
<FormLabel>Title</FormLabel> <FormLabel>Title</FormLabel>
<FormControl> <FormControl>
<Input placeholder="My Link Title" {...field} /> <Input placeholder="My Link Title" {...field} value={field.value ?? ""} />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
A descriptive title for your link (max 100 characters). A descriptive title for your link (max 100 characters).
@@ -338,8 +344,13 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) {
type="number" type="number"
placeholder="100" placeholder="100"
{...field} {...field}
value={field.value || ""} value={field.value ?? ""}
onChange={(e) => field.onChange(e.target.value ? parseInt(e.target.value) : undefined)} onChange={e =>
field.onChange(
isNaN(e.target.valueAsNumber)
? null
: e.target.valueAsNumber
)}
/> />
</FormControl> </FormControl>
<FormDescription> <FormDescription>

View File

@@ -12,15 +12,11 @@ import { cn } from "@/lib/utils"
interface DatePickerProps { interface DatePickerProps {
value?: Date value?: Date
onChange?: (date: Date | undefined) => void onChange?: (date: Date | undefined) => void
disabled?: boolean
className?: string
} }
export function DatePicker({ export function DatePicker({
value, value,
onChange, onChange
disabled = false,
className
}: DatePickerProps) { }: DatePickerProps) {
return ( return (
<Popover> <Popover>
@@ -29,10 +25,8 @@ export function DatePicker({
variant="outline" variant="outline"
className={cn( className={cn(
"w-full justify-start text-left font-normal", "w-full justify-start text-left font-normal",
!value && "text-muted-foreground", !value && "text-muted-foreground"
className
)} )}
disabled={disabled}
> >
<CalendarIcon className="mr-2 h-4 w-4" /> <CalendarIcon className="mr-2 h-4 w-4" />
{value ? format(value, "PPP") : <span>Pick a date</span>} {value ? format(value, "PPP") : <span>Pick a date</span>}

View File

@@ -14,8 +14,8 @@ export const urls = pgTable("urls", {
title: varchar("title"), title: varchar("title"),
maxVisits: integer("max_visits"), maxVisits: integer("max_visits"),
expDate: timestamp("exp_date", { withTimezone: true }), expDate: timestamp("exp_date", { withTimezone: true }),
forwardQueryParams: boolean("forward_query_params").default(true), forwardQueryParams: boolean("forward_query_params").notNull().default(true),
crawlable: boolean("crawable").default(false), crawlable: boolean("crawable").notNull().default(false),
createdAt, createdAt,
updatedAt updatedAt
}, (t) => { }, (t) => {

View File

@@ -7,20 +7,20 @@ export const urlFormSchema = z.object({
export const advancedUrlSchema = z.object({ export const advancedUrlSchema = z.object({
url: z.string().url("Please enter a valid URL"), url: z.string().url("Please enter a valid URL"),
slug: z.string().max(10, "Slug must be 10 characters or less"), slug: z.string().max(10, "Slug must be 10 characters or less").transform(v => v.trim() === "" ? null : v).nullable(),
title: z.string().max(100, "Title must be 100 characters or less"), title: z.string().max(100, "Title must be 100 characters or less").transform(v => v.trim() === "" ? null : v).nullable(),
maxVisits: z.number().int(), maxVisits: z.number().int().positive().nullable(),
expDate: z.date().optional(), expDate: z.date().optional(),
forwardQueryParams: z.boolean(), forwardQueryParams: z.boolean(),
crawlable: z.boolean(), crawlable: z.boolean(),
}) })
export const editUrlSchema = z.object({ export const editUrlSchema = z.object({
url: z.string().url("Please enter a valid URL").optional(), url: z.string().url("Please enter a valid URL"),
slug: z.string().max(10, "Slug must be 10 characters or less").optional(), slug: z.string().max(10, "Slug must be 10 characters or less"),
title: z.string().max(100, "Title must be 100 characters or less").optional(), title: z.string().max(100, "Title must be 100 characters or less").transform(v => v.trim() === "" ? null : v).nullable(),
maxVisits: z.number().int().optional(), maxVisits: z.number().int().positive().nullable(),
expDate: z.date().optional(), expDate: z.date().optional(),
forwardQueryParams: z.boolean().optional(), forwardQueryParams: z.boolean(),
crawlable: z.boolean().optional(), crawlable: z.boolean(),
}) })