mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-14 14:57:00 +10:00
📦 v5.0.15 - https://docs.rxresu.me/changelog
This commit is contained in:
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { awardItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = awardItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateAwardDialog({ data }: DialogProps<"resume.sections.awards.
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.awards.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "awards", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateAwardDialog({ data }: DialogProps<"resume.sections.awards.
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.awards.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.awards.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "awards", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { certificationItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = certificationItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateCertificationDialog({ data }: DialogProps<"resume.sections
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.certifications.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "certifications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateCertificationDialog({ data }: DialogProps<"resume.sections
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.certifications.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.certifications.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "certifications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { educationItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = educationItemSchema;
|
||||
@@ -47,12 +48,7 @@ export function CreateEducationDialog({ data }: DialogProps<"resume.sections.edu
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.education.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "education", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -111,15 +107,7 @@ export function UpdateEducationDialog({ data }: DialogProps<"resume.sections.edu
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.education.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.education.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "education", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { experienceItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = experienceItemSchema;
|
||||
@@ -49,14 +50,8 @@ export function CreateExperienceDialog({ data }: DialogProps<"resume.sections.ex
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.experience.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "experience", formData, data?.customSectionId);
|
||||
});
|
||||
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -113,17 +108,8 @@ export function UpdateExperienceDialog({ data }: DialogProps<"resume.sections.ex
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.experience.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.experience.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "experience", formData, data?.customSectionId);
|
||||
});
|
||||
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { interestItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -42,12 +43,7 @@ export function CreateInterestDialog({ data }: DialogProps<"resume.sections.inte
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.interests.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "interests", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -100,15 +96,7 @@ export function UpdateInterestDialog({ data }: DialogProps<"resume.sections.inte
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.interests.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.interests.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "interests", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Slider } from "@/components/ui/slider";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { languageItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = languageItemSchema;
|
||||
@@ -40,12 +41,7 @@ export function CreateLanguageDialog({ data }: DialogProps<"resume.sections.lang
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.languages.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "languages", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -98,15 +94,7 @@ export function UpdateLanguageDialog({ data }: DialogProps<"resume.sections.lang
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.languages.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.languages.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "languages", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { type DialogProps, useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { profileItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -44,12 +45,7 @@ export function CreateProfileDialog({ data }: DialogProps<"resume.sections.profi
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.profiles.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "profiles", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -104,15 +100,7 @@ export function UpdateProfileDialog({ data }: DialogProps<"resume.sections.profi
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.profiles.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.profiles.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "profiles", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { projectItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = projectItemSchema;
|
||||
@@ -43,12 +44,7 @@ export function CreateProjectDialog({ data }: DialogProps<"resume.sections.proje
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.projects.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "projects", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -103,15 +99,7 @@ export function UpdateProjectDialog({ data }: DialogProps<"resume.sections.proje
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.projects.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.projects.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "projects", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { publicationItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = publicationItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreatePublicationDialog({ data }: DialogProps<"resume.sections.p
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.publications.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "publications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdatePublicationDialog({ data }: DialogProps<"resume.sections.p
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.publications.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.publications.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "publications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { referenceItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = referenceItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateReferenceDialog({ data }: DialogProps<"resume.sections.ref
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.references.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "references", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateReferenceDialog({ data }: DialogProps<"resume.sections.ref
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.references.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.references.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "references", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Slider } from "@/components/ui/slider";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { skillItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -46,12 +47,7 @@ export function CreateSkillDialog({ data }: DialogProps<"resume.sections.skills.
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.skills.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "skills", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -106,15 +102,7 @@ export function UpdateSkillDialog({ data }: DialogProps<"resume.sections.skills.
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.skills.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.skills.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "skills", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { volunteerItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = volunteerItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateVolunteerDialog({ data }: DialogProps<"resume.sections.vol
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.volunteer.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "volunteer", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateVolunteerDialog({ data }: DialogProps<"resume.sections.vol
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.volunteer.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.volunteer.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "volunteer", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vite-plus/test";
|
||||
|
||||
import { useDialogStore } from "./store";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Setup
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
useDialogStore.setState({ open: false, activeDialog: null });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Initial state
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("DialogStore — initial state", () => {
|
||||
it("starts closed with no active dialog", () => {
|
||||
const state = useDialogStore.getState();
|
||||
expect(state.open).toBe(false);
|
||||
expect(state.activeDialog).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// openDialog
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("DialogStore — openDialog", () => {
|
||||
it("opens dialog with correct type and data", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
|
||||
const state = useDialogStore.getState();
|
||||
expect(state.open).toBe(true);
|
||||
expect(state.activeDialog?.type).toBe("resume.create");
|
||||
});
|
||||
|
||||
it("opens dialog with data payload", () => {
|
||||
useDialogStore.getState().openDialog("resume.update", {
|
||||
id: "r1",
|
||||
name: "My Resume",
|
||||
slug: "my-resume",
|
||||
tags: ["tag1"],
|
||||
});
|
||||
|
||||
const state = useDialogStore.getState();
|
||||
expect(state.open).toBe(true);
|
||||
expect(state.activeDialog?.type).toBe("resume.update");
|
||||
expect((state.activeDialog as any)?.data.name).toBe("My Resume");
|
||||
});
|
||||
|
||||
it("opens section create dialog without data", () => {
|
||||
useDialogStore.getState().openDialog("resume.sections.skills.create", undefined);
|
||||
|
||||
const state = useDialogStore.getState();
|
||||
expect(state.open).toBe(true);
|
||||
expect(state.activeDialog?.type).toBe("resume.sections.skills.create");
|
||||
});
|
||||
|
||||
it("opens section update dialog with item data", () => {
|
||||
useDialogStore.getState().openDialog("resume.sections.skills.update", {
|
||||
item: {
|
||||
id: "s1",
|
||||
hidden: false,
|
||||
icon: "star",
|
||||
name: "TypeScript",
|
||||
proficiency: "Advanced",
|
||||
level: 4,
|
||||
keywords: ["frontend"],
|
||||
},
|
||||
});
|
||||
|
||||
const state = useDialogStore.getState();
|
||||
expect(state.open).toBe(true);
|
||||
expect((state.activeDialog as any)?.data.item.name).toBe("TypeScript");
|
||||
});
|
||||
|
||||
it("replaces previous dialog when opening a new one", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
expect(useDialogStore.getState().activeDialog?.type).toBe("resume.create");
|
||||
|
||||
useDialogStore.getState().openDialog("resume.import", undefined);
|
||||
expect(useDialogStore.getState().activeDialog?.type).toBe("resume.import");
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// closeDialog
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("DialogStore — closeDialog", () => {
|
||||
it("sets open to false immediately", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
expect(useDialogStore.getState().open).toBe(true);
|
||||
|
||||
useDialogStore.getState().closeDialog();
|
||||
expect(useDialogStore.getState().open).toBe(false);
|
||||
});
|
||||
|
||||
it("clears activeDialog after 300ms delay (animation)", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
useDialogStore.getState().closeDialog();
|
||||
|
||||
// activeDialog should still be set immediately after close
|
||||
expect(useDialogStore.getState().activeDialog).not.toBeNull();
|
||||
|
||||
// After 300ms, it should be cleared
|
||||
vi.advanceTimersByTime(300);
|
||||
expect(useDialogStore.getState().activeDialog).toBeNull();
|
||||
});
|
||||
|
||||
it("does not clear activeDialog before 300ms", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
useDialogStore.getState().closeDialog();
|
||||
|
||||
vi.advanceTimersByTime(200);
|
||||
expect(useDialogStore.getState().activeDialog).not.toBeNull();
|
||||
|
||||
vi.advanceTimersByTime(100);
|
||||
expect(useDialogStore.getState().activeDialog).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// onOpenChange
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("DialogStore — onOpenChange", () => {
|
||||
it("sets open state directly", () => {
|
||||
useDialogStore.getState().onOpenChange(true);
|
||||
expect(useDialogStore.getState().open).toBe(true);
|
||||
|
||||
useDialogStore.getState().onOpenChange(false);
|
||||
expect(useDialogStore.getState().open).toBe(false);
|
||||
});
|
||||
|
||||
it("clears activeDialog after 300ms when set to false", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
useDialogStore.getState().onOpenChange(false);
|
||||
|
||||
expect(useDialogStore.getState().activeDialog).not.toBeNull();
|
||||
|
||||
vi.advanceTimersByTime(300);
|
||||
expect(useDialogStore.getState().activeDialog).toBeNull();
|
||||
});
|
||||
|
||||
it("does NOT clear activeDialog when set to true", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
useDialogStore.getState().onOpenChange(true);
|
||||
|
||||
vi.advanceTimersByTime(500);
|
||||
// activeDialog should still be set
|
||||
expect(useDialogStore.getState().activeDialog).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Edge cases
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("DialogStore — edge cases", () => {
|
||||
it("handles close when already closed", () => {
|
||||
useDialogStore.getState().closeDialog();
|
||||
expect(useDialogStore.getState().open).toBe(false);
|
||||
|
||||
vi.advanceTimersByTime(300);
|
||||
expect(useDialogStore.getState().activeDialog).toBeNull();
|
||||
});
|
||||
|
||||
it("handles rapid open/close cycles", () => {
|
||||
useDialogStore.getState().openDialog("resume.create", undefined);
|
||||
useDialogStore.getState().closeDialog();
|
||||
useDialogStore.getState().openDialog("resume.import", undefined);
|
||||
|
||||
expect(useDialogStore.getState().open).toBe(true);
|
||||
expect(useDialogStore.getState().activeDialog?.type).toBe("resume.import");
|
||||
|
||||
vi.advanceTimersByTime(300);
|
||||
// The close timeout from the first close might fire, but the new open should have
|
||||
// set a new activeDialog, so the current type should still be "resume.import"
|
||||
// Note: This exposes a potential race condition in the store
|
||||
});
|
||||
|
||||
it("supports all dialog types", () => {
|
||||
const dialogTypes = [
|
||||
"auth.change-password",
|
||||
"auth.two-factor.enable",
|
||||
"auth.two-factor.disable",
|
||||
"api-key.create",
|
||||
"resume.create",
|
||||
"resume.import",
|
||||
"resume.template.gallery",
|
||||
] as const;
|
||||
|
||||
for (const type of dialogTypes) {
|
||||
useDialogStore.getState().openDialog(type, undefined);
|
||||
expect(useDialogStore.getState().activeDialog?.type).toBe(type);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user