mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-14 23:07:01 +10:00
@@ -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>
|
||||
|
||||
@@ -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 },
|
||||
{
|
||||
|
||||
@@ -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."),
|
||||
|
||||
Reference in New Issue
Block a user