diff --git a/src/app/(admin)/dashboard/_components/url-form-card.tsx b/src/app/(admin)/dashboard/_components/url-form-card.tsx index 1962cfd..c2eb679 100644 --- a/src/app/(admin)/dashboard/_components/url-form-card.tsx +++ b/src/app/(admin)/dashboard/_components/url-form-card.tsx @@ -23,9 +23,9 @@ function AdvancedUrlForm() { resolver: zodResolver(advancedUrlSchema), defaultValues: { url: "", - slug: "", - title: "", - maxVisits: 0, + slug: null, + title: null, + maxVisits: null, expDate: undefined, forwardQueryParams: true, crawlable: false @@ -71,7 +71,7 @@ function AdvancedUrlForm() { Custom Slug (Optional) - + A unique identifier for your short link (max 10 characters). @@ -133,7 +133,7 @@ function AdvancedUrlForm() { Title (Optional) - + A descriptive title for your link (max 100 characters). @@ -153,7 +153,13 @@ function AdvancedUrlForm() { type="number" placeholder="100" {...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 + )} /> @@ -205,11 +211,11 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) { defaultValues: { url: data.url, slug: data.slug, - title: data.title || "", - maxVisits: data.maxVisits || undefined, + title: data.title || null, + maxVisits: data.maxVisits || null, expDate: data.expDate || undefined, - forwardQueryParams: data.forwardQueryParams || undefined, - crawlable: data.crawlable || undefined + forwardQueryParams: data.forwardQueryParams, + crawlable: data.crawlable } }) @@ -318,7 +324,7 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) { Title - + A descriptive title for your link (max 100 characters). @@ -338,8 +344,13 @@ function EditUrlForm({ data }: { data: typeof urls.$inferSelect }) { type="number" placeholder="100" {...field} - value={field.value || ""} - 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 + )} /> diff --git a/src/components/date-picker.tsx b/src/components/date-picker.tsx index 429971f..407373f 100644 --- a/src/components/date-picker.tsx +++ b/src/components/date-picker.tsx @@ -12,15 +12,11 @@ import { cn } from "@/lib/utils" interface DatePickerProps { value?: Date onChange?: (date: Date | undefined) => void - disabled?: boolean - className?: string } export function DatePicker({ value, - onChange, - disabled = false, - className + onChange }: DatePickerProps) { return ( @@ -29,10 +25,8 @@ export function DatePicker({ variant="outline" className={cn( "w-full justify-start text-left font-normal", - !value && "text-muted-foreground", - className + !value && "text-muted-foreground" )} - disabled={disabled} > {value ? format(value, "PPP") : Pick a date} diff --git a/src/lib/drizzle/schema.ts b/src/lib/drizzle/schema.ts index 180b4f8..6b1f37c 100644 --- a/src/lib/drizzle/schema.ts +++ b/src/lib/drizzle/schema.ts @@ -14,8 +14,8 @@ export const urls = pgTable("urls", { title: varchar("title"), maxVisits: integer("max_visits"), expDate: timestamp("exp_date", { withTimezone: true }), - forwardQueryParams: boolean("forward_query_params").default(true), - crawlable: boolean("crawable").default(false), + forwardQueryParams: boolean("forward_query_params").notNull().default(true), + crawlable: boolean("crawable").notNull().default(false), createdAt, updatedAt }, (t) => { diff --git a/src/lib/schema/url.ts b/src/lib/schema/url.ts index 0cae166..a769797 100644 --- a/src/lib/schema/url.ts +++ b/src/lib/schema/url.ts @@ -7,20 +7,20 @@ export const urlFormSchema = z.object({ export const advancedUrlSchema = z.object({ url: z.string().url("Please enter a valid URL"), - slug: z.string().max(10, "Slug must be 10 characters or less"), - title: z.string().max(100, "Title must be 100 characters or less"), - maxVisits: z.number().int(), + 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").transform(v => v.trim() === "" ? null : v).nullable(), + maxVisits: z.number().int().positive().nullable(), expDate: z.date().optional(), forwardQueryParams: z.boolean(), crawlable: z.boolean(), }) export const editUrlSchema = z.object({ - url: z.string().url("Please enter a valid URL").optional(), - slug: z.string().max(10, "Slug must be 10 characters or less").optional(), - title: z.string().max(100, "Title must be 100 characters or less").optional(), - maxVisits: z.number().int().optional(), + url: z.string().url("Please enter a valid URL"), + slug: z.string().max(10, "Slug must be 10 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().positive().nullable(), expDate: z.date().optional(), - forwardQueryParams: z.boolean().optional(), - crawlable: z.boolean().optional(), + forwardQueryParams: z.boolean(), + crawlable: z.boolean(), }) \ No newline at end of file