mirror of
https://github.com/JOYCEQL/magic-resume.git
synced 2026-07-03 14:07:11 +02:00
fix: react component control problem
This commit is contained in:
@@ -19,7 +19,9 @@ import {
|
||||
|
||||
export function EditPanel() {
|
||||
const { activeResume, updateMenuSections } = useResumeStore();
|
||||
const { activeSection, menuSections = [] } = activeResume || {};
|
||||
if (!activeResume) return;
|
||||
const { activeSection = "", menuSections = [] } = activeResume || {};
|
||||
|
||||
const renderFields = () => {
|
||||
switch (activeSection) {
|
||||
case "basic":
|
||||
|
||||
@@ -6,7 +6,7 @@ import { motion } from "framer-motion";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@@ -30,7 +30,7 @@ const Field: React.FC<FieldProps> = ({
|
||||
type = "text",
|
||||
placeholder,
|
||||
required,
|
||||
className
|
||||
className,
|
||||
}) => {
|
||||
const renderLabel = () => (
|
||||
<span
|
||||
@@ -96,7 +96,7 @@ const Field: React.FC<FieldProps> = ({
|
||||
{required && <span className="text-red-500">*</span>}
|
||||
</span>
|
||||
<motion.textarea
|
||||
value={value}
|
||||
value={value || ""}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
className={inputStyles}
|
||||
@@ -114,7 +114,7 @@ const Field: React.FC<FieldProps> = ({
|
||||
{renderLabel()}
|
||||
<div className="mt-1.5">
|
||||
<RichTextEditor
|
||||
content={value}
|
||||
content={value || ""}
|
||||
onChange={onChange}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
@@ -136,7 +136,7 @@ const Field: React.FC<FieldProps> = ({
|
||||
</span>
|
||||
<Input
|
||||
type="text"
|
||||
value={value}
|
||||
value={value || ""}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
className={inputStyles}
|
||||
|
||||
@@ -62,30 +62,42 @@ const CustomField: React.FC<CustomFieldProps> = ({
|
||||
onChange={(value) => onUpdate({ ...field, icon: value })}
|
||||
/>
|
||||
</div>
|
||||
<Field
|
||||
label=""
|
||||
value={field.label}
|
||||
onChange={(value) => onUpdate({ ...field, label: value })}
|
||||
placeholder="字段名称"
|
||||
className={cn(
|
||||
"bg-neutral-50 dark:bg-neutral-900",
|
||||
"border-neutral-200 dark:border-neutral-700",
|
||||
"focus:border-blue-500 dark:focus:border-blue-400",
|
||||
"placeholder-neutral-400 dark:placeholder-neutral-500"
|
||||
)}
|
||||
/>
|
||||
<Field
|
||||
label=""
|
||||
value={field.value}
|
||||
onChange={(value) => onUpdate({ ...field, value })}
|
||||
placeholder="字段内容"
|
||||
className={cn(
|
||||
"bg-neutral-50 dark:bg-neutral-900",
|
||||
"border-neutral-200 dark:border-neutral-700",
|
||||
"focus:border-blue-500 dark:focus:border-blue-400",
|
||||
"placeholder-neutral-400 dark:placeholder-neutral-500"
|
||||
)}
|
||||
/>
|
||||
<div className="col-span-2">
|
||||
<Field
|
||||
value={field.label ?? ""}
|
||||
onChange={(value) =>
|
||||
onUpdate({
|
||||
...field,
|
||||
label: value,
|
||||
})
|
||||
}
|
||||
placeholder="标签"
|
||||
className={cn(
|
||||
"bg-neutral-50 dark:bg-neutral-900",
|
||||
"border-neutral-200 dark:border-neutral-700",
|
||||
"focus:border-blue-500 dark:focus:border-blue-400",
|
||||
"placeholder-neutral-400 dark:placeholder-neutral-500"
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Field
|
||||
value={field.value ?? ""}
|
||||
onChange={(value) =>
|
||||
onUpdate({
|
||||
...field,
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
placeholder="值"
|
||||
className={cn(
|
||||
"bg-neutral-50 dark:bg-neutral-900",
|
||||
"border-neutral-200 dark:border-neutral-700",
|
||||
"focus:border-blue-500 dark:focus:border-blue-400",
|
||||
"placeholder-neutral-400 dark:placeholder-neutral-500"
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{field.visible ? (
|
||||
<Eye
|
||||
@@ -254,7 +266,7 @@ const BasicPanel: React.FC = () => {
|
||||
<div className="flex-1">
|
||||
<Field
|
||||
label=""
|
||||
value={(basic?.[field.key] as string) || ""}
|
||||
value={(basic?.[field.key] as string) ?? ""}
|
||||
onChange={(value) =>
|
||||
updateBasicInfo({
|
||||
...basic,
|
||||
|
||||
@@ -357,7 +357,7 @@ const HeadingSelect = ({ editor }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const RichTextEditor = ({ content, onChange }: RichTextEditorProps) => {
|
||||
const RichTextEditor = ({ content = "", onChange }: RichTextEditorProps) => {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit.configure({
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Project,
|
||||
CustomItem,
|
||||
ResumeData,
|
||||
MenuSection,
|
||||
} from "../types/resume";
|
||||
|
||||
interface ResumeStore {
|
||||
@@ -400,9 +401,19 @@ export const useResumeStore = create<ResumeStore>()(
|
||||
},
|
||||
|
||||
reorderSections: (newOrder) => {
|
||||
const { activeResumeId } = get();
|
||||
const { activeResumeId, resumes } = get();
|
||||
if (activeResumeId) {
|
||||
get().updateResume(activeResumeId, { menuSections: newOrder });
|
||||
const currentResume = resumes[activeResumeId];
|
||||
const basicInfoSection = currentResume.menuSections.find(
|
||||
(section) => section.id === "basic"
|
||||
);
|
||||
const reorderedSections = [
|
||||
basicInfoSection,
|
||||
...newOrder.filter((section) => section.id !== "basic"),
|
||||
];
|
||||
get().updateResume(activeResumeId, {
|
||||
menuSections: reorderedSections as MenuSection[],
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -163,6 +163,14 @@ export const THEME_COLORS = [
|
||||
"#dc2626",
|
||||
];
|
||||
|
||||
export interface MenuSection {
|
||||
id: string;
|
||||
title: string;
|
||||
icon: string;
|
||||
enabled: boolean;
|
||||
order: number;
|
||||
}
|
||||
|
||||
export interface ResumeData {
|
||||
id: string;
|
||||
title: string;
|
||||
@@ -178,13 +186,7 @@ export interface ResumeData {
|
||||
activeSection: string;
|
||||
colorTheme: string;
|
||||
draggingProjectId: string | null;
|
||||
menuSections: {
|
||||
id: string;
|
||||
title: string;
|
||||
icon: string;
|
||||
enabled: boolean;
|
||||
order: number;
|
||||
}[];
|
||||
menuSections: MenuSection[];
|
||||
globalSettings: GlobalSettings;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user