From 46a80f237d982e5b321d678ba60004bda33b88a7 Mon Sep 17 00:00:00 2001 From: JOYCEQL <1449239013@qq.com> Date: Fri, 17 Jan 2025 02:10:25 +0800 Subject: [PATCH] feat: import resume json --- .../src/app/app/dashboard/resumes/page.tsx | 151 +++++++++++++----- apps/fronted/src/i18n/locales/en.json | 18 ++- apps/fronted/src/i18n/locales/zh.json | 6 +- apps/fronted/src/store/useResumeStore.ts | 13 ++ 4 files changed, 145 insertions(+), 43 deletions(-) diff --git a/apps/fronted/src/app/app/dashboard/resumes/page.tsx b/apps/fronted/src/app/app/dashboard/resumes/page.tsx index a69d3dc..64e48e5 100644 --- a/apps/fronted/src/app/app/dashboard/resumes/page.tsx +++ b/apps/fronted/src/app/app/dashboard/resumes/page.tsx @@ -2,9 +2,15 @@ import React, { useEffect } from "react"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; -import { Plus, FileText, Settings, AlertCircle } from "lucide-react"; +import { Plus, FileText, Settings, AlertCircle, Upload } from "lucide-react"; import { motion, AnimatePresence } from "framer-motion"; +import { toast } from "sonner"; import { Button } from "@/components/ui/button"; +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; +import { getConfig, getFileHandle, verifyPermission } from "@/utils/fileSystem"; +import { useResumeStore } from "@/store/useResumeStore"; +import { cn } from "@/lib/utils"; +import { initialResumeState } from "@/config/initialResumeData"; import { Card, CardContent, @@ -12,27 +18,24 @@ import { CardFooter, CardTitle, } from "@/components/ui/card"; -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { getConfig, getFileHandle, verifyPermission } from "@/utils/fileSystem"; -import { useResumeStore } from "@/store/useResumeStore"; -import { cn } from "@/lib/utils"; const ResumesList = () => { return ; }; const ResumeWorkbench = () => { + const t = useTranslations(); const { resumes, - createResume, - deleteResume, setActiveResume, updateResume, updateResumeFromFile, + addResume, + deleteResume, + createResume, } = useResumeStore(); const router = useRouter(); const [hasConfiguredFolder, setHasConfiguredFolder] = React.useState(false); - const t = useTranslations(); useEffect(() => { const syncResumesFromFiles = async () => { @@ -88,6 +91,39 @@ const ResumeWorkbench = () => { setActiveResume(newId); }; + const handleImportJson = () => { + const input = document.createElement("input"); + input.type = "file"; + input.accept = ".json"; + + input.onchange = async (e) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (!file) return; + + try { + const content = await file.text(); + const config = JSON.parse(content); + + const newResume = { + ...initialResumeState, + ...config, + id: crypto.randomUUID(), + title: config.title || t("dashboard.resumes.untitled"), + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + addResume(newResume); + toast.success(t("dashboard.resumes.importSuccess")); + } catch (error) { + console.error("Import error:", error); + toast.error(t("dashboard.resumes.importError")); + } + }; + + input.click(); + }; + return ( { transition={{ duration: 0.3, delay: 0.1 }} > {hasConfiguredFolder ? ( - + - + {t("dashboard.resumes.synced")} - + + + + + + { > - + - + {t("dashboard.resumes.newResume")} - + {t("dashboard.resumes.newResumeDescription")} @@ -215,22 +279,23 @@ const ResumeWorkbench = () => { > - + - + {resume.title || "未命名简历"} - + {t("dashboard.resumes.created")} {new Date(resume.createdAt).toLocaleDateString()} @@ -242,10 +307,15 @@ const ResumeWorkbench = () => {