This commit is contained in:
Amruth Pillai
2026-01-26 12:38:37 +01:00
parent 1e814a77cc
commit 429618d5f8
3 changed files with 20 additions and 29 deletions
+16 -21
View File
@@ -3,7 +3,7 @@ import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { DownloadSimpleIcon, FileIcon, UploadSimpleIcon } from "@phosphor-icons/react";
import { useMutation } from "@tanstack/react-query";
import { useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import { useForm, useWatch } from "react-hook-form";
import { toast } from "sonner";
import z from "zod";
@@ -66,10 +66,11 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
const { enabled: isAIEnabled, provider, model, apiKey, baseURL } = useAIStore();
const closeDialog = useDialogStore((state) => state.closeDialog);
const inputRef = useRef<HTMLInputElement>(null);
const prevTypeRef = useRef<string>("");
const inputRef = useRef<HTMLInputElement>(null);
const [isLoading, setIsLoading] = useState<boolean>(false);
const { mutateAsync: importResume, isPending } = useMutation(orpc.resume.import.mutationOptions());
const { mutateAsync: importResume } = useMutation(orpc.resume.import.mutationOptions());
const form = useForm<FormValues>({
resolver: zodResolver(formSchema),
@@ -100,6 +101,8 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
const onSubmit = async (values: FormValues) => {
if (values.type === "") return;
setIsLoading(true);
const toastId = toast.loading(t`Importing your resume...`, {
description: t`This may take a few minutes, depending on the response of the AI provider. Please do not close the window or refresh the page.`,
});
@@ -126,13 +129,8 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
}
if (values.type === "pdf") {
if (!isAIEnabled) {
toast.error(t`This feature requires AI Integration to be enabled. Please enable it in the settings.`, {
id: toastId,
description: null,
});
return;
}
if (!isAIEnabled)
throw new Error(t`This feature requires AI Integration to be enabled. Please enable it in the settings.`);
const arrayBuffer = await values.file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
@@ -147,13 +145,8 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
}
if (values.type === "docx") {
if (!isAIEnabled) {
toast.error(t`This feature requires AI Integration to be enabled. Please enable it in the settings.`, {
id: toastId,
description: null,
});
return;
}
if (!isAIEnabled)
throw new Error(t`This feature requires AI Integration to be enabled. Please enable it in the settings.`);
const arrayBuffer = await values.file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
@@ -172,7 +165,7 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
});
}
if (!data) return;
if (!data) throw new Error("No data was returned from the AI provider.");
await importResume({ data });
toast.success(t`Your resume has been imported successfully.`, { id: toastId, description: null });
@@ -183,6 +176,8 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
} else {
toast.error(t`An unknown error occurred while importing your resume.`, { id: toastId, description: null });
}
} finally {
setIsLoading(false);
}
};
@@ -279,9 +274,9 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
/>
<DialogFooter>
<Button type="submit" disabled={!type || isPending}>
{isPending ? <Spinner /> : null}
{isPending ? t`Importing...` : t`Import`}
<Button type="submit" disabled={!type || isLoading}>
{isLoading ? <Spinner /> : null}
{isLoading ? t`Importing...` : t`Import`}
</Button>
</DialogFooter>
</form>
+2 -6
View File
@@ -82,9 +82,7 @@ export const aiRouter = {
const result = await generateText({
model,
maxRetries: 0,
output: Output.object({
schema: resumeDataSchema.omit({ picture: true, metadata: true, customSections: true }),
}),
output: Output.object({ schema: resumeDataSchema }),
messages: [
{
role: "system",
@@ -139,9 +137,7 @@ export const aiRouter = {
const result = await generateText({
model,
maxRetries: 0,
output: Output.object({
schema: resumeDataSchema.omit({ picture: true, metadata: true, customSections: true }),
}),
output: Output.object({ schema: resumeDataSchema }),
messages: [
{ role: "system", content: docxParserSystemPrompt },
{
+2 -2
View File
@@ -61,13 +61,13 @@ export const customFieldSchema = z.object({
id: z.string().describe("The unique identifier for the custom field. Usually generated as a UUID."),
icon: iconSchema,
text: z.string().describe("The text to display for the custom field."),
link: z.url().or(z.literal("")).describe("If the custom field should be a link, the URL to link to.").catch(""),
link: z.string().describe("If the custom field should be a link, the URL to link to.").catch(""),
});
export const basicsSchema = z.object({
name: z.string().describe("The full name of the author of the resume."),
headline: z.string().describe("The headline of the author of the resume."),
email: z.email().or(z.literal("")).describe("The email address of the author of the resume."),
email: z.string().describe("The email address of the author of the resume."),
phone: z.string().describe("The phone number of the author of the resume."),
location: z.string().describe("The location of the author of the resume."),
website: urlSchema.describe("The website of the author of the resume."),