mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-15 02:53:25 +10:00
fix: address Greptile review on margin clamping
Add .catch() fallbacks for marginX/marginY so oversized stored values recover instead of failing schema parse, and allow transient empty numeric input in the form without persisting invalid metadata. Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
This commit is contained in:
co-authored by
Amruth Pillai
parent
f55e584e34
commit
1aca52b0d7
@@ -55,7 +55,12 @@ function PageSectionForm() {
|
||||
useSyncFormValues(form, page);
|
||||
|
||||
const handleAutoSave = <K extends keyof FormValues>(name: K, value: FormValues[K]) => {
|
||||
persist({ ...form.state.values, [name]: value });
|
||||
const next = { ...form.state.values, [name]: value };
|
||||
// Keep last-saved numeric page fields when the form holds a transient empty/NaN value
|
||||
for (const key of ["marginX", "marginY", "gapX", "gapY"] as const) {
|
||||
if (!Number.isFinite(next[key])) next[key] = page?.[key] ?? 0;
|
||||
}
|
||||
persist(next);
|
||||
};
|
||||
|
||||
const pageNumberFields = [
|
||||
@@ -148,7 +153,7 @@ function PageSectionForm() {
|
||||
render={
|
||||
<InputGroupInput
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
value={Number.isFinite(field.state.value) ? field.state.value : ""}
|
||||
min={min}
|
||||
{...(max !== undefined ? { max } : {})}
|
||||
step={1}
|
||||
@@ -156,8 +161,11 @@ function PageSectionForm() {
|
||||
onBlur={field.handleBlur}
|
||||
onChange={(e) => {
|
||||
const v = e.target.value;
|
||||
// Ignore transient empty/invalid input so resume metadata stays numeric
|
||||
if (v === "") return;
|
||||
if (v === "") {
|
||||
// Allow clearing the controlled input without persisting invalid metadata
|
||||
field.handleChange(Number.NaN);
|
||||
return;
|
||||
}
|
||||
|
||||
const raw = Number(v);
|
||||
if (!Number.isFinite(raw)) return;
|
||||
|
||||
@@ -260,6 +260,19 @@ describe("pageSchema", () => {
|
||||
expect(pageSchema.safeParse(invalid).success).toBe(false);
|
||||
});
|
||||
|
||||
it("falls back to default margins when out of range via .catch", () => {
|
||||
const result = pageSchema.safeParse({
|
||||
...defaultResumeData.metadata.page,
|
||||
marginX: 1224,
|
||||
marginY: 999,
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
if (result.success) {
|
||||
expect(result.data.marginX).toBe(14);
|
||||
expect(result.data.marginY).toBe(12);
|
||||
}
|
||||
});
|
||||
|
||||
it("falls back to 'a4' for unknown format via .catch", () => {
|
||||
const invalid = { ...defaultResumeData.metadata.page, format: "huge" };
|
||||
const result = pageSchema.safeParse(invalid);
|
||||
|
||||
@@ -444,8 +444,8 @@ export const layoutSchema = z.object({
|
||||
export const pageSchema = z.object({
|
||||
gapX: z.number().min(0).describe("The horizontal gap between the sections of the page, defined in points (pt)."),
|
||||
gapY: z.number().min(0).describe("The vertical gap between the sections of the page, defined in points (pt)."),
|
||||
marginX: z.number().min(0).max(100).describe("The horizontal margin of the page, defined in points (pt)."),
|
||||
marginY: z.number().min(0).max(100).describe("The vertical margin of the page, defined in points (pt)."),
|
||||
marginX: z.number().min(0).max(100).catch(14).describe("The horizontal margin of the page, defined in points (pt)."),
|
||||
marginY: z.number().min(0).max(100).catch(12).describe("The vertical margin of the page, defined in points (pt)."),
|
||||
format: z
|
||||
.enum(["a4", "letter", "free-form"])
|
||||
.describe("The format of the page. Can be 'a4', 'letter', or 'free-form'.")
|
||||
|
||||
Reference in New Issue
Block a user