casualroom/apps/fenghuo/web/components/profile/profile-sheet.tsx

1291 lines
74 KiB
TypeScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import * as React from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import { CalendarIcon, Plus, Trash2 } from 'lucide-react';
import { IconChevronDown, IconCheck, IconX } from '@tabler/icons-react';
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetFooter,
} from '@nice/ui/components/sheet';
import { Button } from '@nice/ui/components/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@nice/ui/components/form';
import { Input } from '@nice/ui/components/input';
import { Textarea } from '@nice/ui/components/textarea';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@nice/ui/components/select';
import { Calendar } from '@nice/ui/components/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '@nice/ui/components/popover';
import { DateTimePicker } from '@nice/ui/components/date-time-picker';
import {
Command,
CommandEmpty,
CommandGroup,
CommandItem,
CommandList,
} from '@nice/ui/components/command';
import { Card, CardContent, CardHeader, CardTitle } from '@nice/ui/components/card';
import { cn } from '@nice/ui/lib/utils';
import { DeptSelect, DutySelect } from '@/components/selector';
import { AvatarUpload } from '@/components/common/avatar-upload';
import { Education, EducationForm, PoliticalStatus, TrainType, AppraisalLevel, ProfileMetadata } from '@fenghuo/common';
import { useProfile } from './profile-provider';
import { useTranslation } from '@nice/i18n';
// 定义表单验证模式
const createProfileFormSchema = (t: (key: string) => string) => z.object({
// 基本信息
name: z.string().min(1, t('profile.profile_sheet.validation.name_required')),
gender: z.number().min(1).max(2),
idNum: z.string().min(15, t('profile.profile_sheet.validation.id_number_min_length')),
paperId: z.string().min(1, t('profile.profile_sheet.validation.certificate_number_required')), // 改为必选
avatar: z.string().optional(), // 添加头像字段,可选
command: z.string(), // 添加编制命令字段
birthday: z.date().optional(), // 添加生日字段
// 入职信息 - 改为必选
hireDate: z.date({ required_error: t('profile.profile_sheet.validation.hire_date_required') }),
relativeHireDate: z.date().optional(),
// 身份信息 - 改为必选
identity: z.string().min(1, t('profile.profile_sheet.validation.identity_required')),
level: z.string().min(1, t('profile.profile_sheet.validation.rank_required')),
levelDate: z.date({ required_error: t('profile.profile_sheet.validation.rank_time_required') }),
// 职务信息 - 改为必选
dutyCode: z.string().optional(),
dutyLevel: z.string().optional(), // 改为非必选
dutyName: z.string().min(1, t('profile.profile_sheet.validation.duty_name_required')),
// 组织信息 - 改为必选
organizationId: z.string().min(1, t('profile.profile_sheet.validation.organization_required')),
// 元数据
metadata: z.object({
ethnicity: z.string().optional(),
bloodType: z.string().optional(),
proxyDuty: z.string().optional(),
isRehire: z.boolean().optional(),
isExtendedDeparture: z.boolean().optional(),
positionYear: z.number().optional(),
politicalStatus: z.string().optional(),
partyPosition: z.string().optional(),
native: z.object({
province: z.string().optional(),
city: z.string().optional(),
county: z.string().optional(),
}).optional(),
education: z.string().optional(),
educationForm: z.string().optional(),
isGraduate: z.boolean().optional(),
schoolMajor: z.string().optional(),
drills: z.number().optional(),
train: z.array(z.object({
type: z.string().optional(),
location: z.string().optional(),
major: z.string().optional(),
})).optional(),
appraisal: z.array(z.object({
level: z.string().optional(),
job: z.string().optional(),
})).optional(),
foreignLanguage: z.string().optional(),
reward: z.string().optional(),
punish: z.string().optional(),
remark: z.string().optional(),
}).optional(),
});
// 职务水平选择器组件
interface DutyLevelSelectProps {
value?: string;
onValueChange?: (value: string) => void;
placeholder?: string;
className?: string;
disabled?: boolean;
}
function DutyLevelSelect({
value,
onValueChange,
placeholder = '请选择职务水平',
className,
disabled = false,
}: DutyLevelSelectProps) {
const { t } = useTranslation();
const [open, setOpen] = React.useState(false);
// 职务水平选项
const dutyLevelOptions = [
{ value: '1', label: t('profile.profile_sheet.duty_level_primary') },
{ value: '2', label: t('profile.profile_sheet.duty_level_middle') },
{ value: '3', label: t('profile.profile_sheet.duty_level_high') },
];
// 获取当前选中的选项
const selectedOption = dutyLevelOptions.find(option => option.value === value);
// 处理选择逻辑
const handleSelect = (selectedValue: string) => {
if (!onValueChange) return;
// 如果点击的是当前已选中的值,则清空选择
if (value === selectedValue) {
onValueChange('');
} else {
onValueChange(selectedValue);
}
setOpen(false);
};
// 清除选择
const handleClear = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onValueChange?.('');
};
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className={cn(
'w-full justify-between text-left font-normal',
!selectedOption && 'text-muted-foreground',
className,
)}
disabled={disabled}
>
<span className="truncate">
{selectedOption ? selectedOption.label : placeholder}
</span>
<div className="flex items-center gap-1 shrink-0">
{selectedOption && (
<div
role="button"
tabIndex={0}
onClick={handleClear}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleClear(e as any);
}
}}
className="flex items-center justify-center w-4 h-4 rounded-sm hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors"
aria-label={t('common.clear_selection')}
>
<IconX className="h-3 w-3" />
</div>
)}
<IconChevronDown className="h-4 w-4 shrink-0 opacity-50" />
</div>
</Button>
</PopoverTrigger>
<PopoverContent className="w-full p-0" style={{ width: 'var(--radix-popover-trigger-width)' }} align="start">
<Command>
<CommandList>
<CommandEmpty>{t('profile.profile_sheet.duty_level_not_found')}</CommandEmpty>
<CommandGroup>
{dutyLevelOptions.map((option) => (
<CommandItem
key={option.value}
value={option.value}
onSelect={() => handleSelect(option.value)}
className={cn(
'flex items-center justify-between cursor-pointer',
'hover:bg-accent hover:text-accent-foreground',
value === option.value && 'bg-accent text-accent-foreground',
)}
>
<span>{option.label}</span>
{value === option.value && (
<IconCheck className="h-4 w-4 text-primary" />
)}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
}
export function ProfileSheet() {
const { t } = useTranslation();
const {
isSheetOpen,
setIsSheetOpen,
editingProfile,
sheetMode,
handleSubmitEmployee,
} = useProfile();
// 创建动态的表单验证模式
const profileFormSchema = React.useMemo(() => createProfileFormSchema(t), [t]);
type ProfileFormValues = z.infer<typeof profileFormSchema>;
const form = useForm<ProfileFormValues>({
resolver: zodResolver(profileFormSchema),
defaultValues: {
name: '',
gender: 1,
idNum: '',
paperId: '',
avatar: '',
command: '',
birthday: undefined,
hireDate: undefined, // 改为 undefined保持一致性
relativeHireDate: undefined, // 改为 undefined保持一致性
identity: '',
level: '',
levelDate: undefined, // 改为 undefined保持一致性
dutyCode: '',
dutyLevel: '',
dutyName: '',
organizationId: '',
metadata: {
ethnicity: '',
bloodType: '',
proxyDuty: '',
isRehire: false,
isExtendedDeparture: false,
positionYear: undefined,
politicalStatus: '',
partyPosition: '',
native: {
province: '',
city: '',
county: '',
},
education: '',
educationForm: '',
isGraduate: false,
schoolMajor: '',
drills: undefined,
train: [{ type: '', location: '', major: '' }],
appraisal: [{ level: '', job: '' }],
foreignLanguage: '',
reward: '',
punish: '',
remark: '',
},
},
});
// 当编辑数据变化时,回显数据
React.useEffect(() => {
if (editingProfile && sheetMode === 'edit') {
const metadata = editingProfile.metadata as ProfileMetadata;
form.reset({
name: editingProfile.name || '',
gender: editingProfile.gender || 1,
idNum: editingProfile.idNum || '',
paperId: editingProfile.paperId || '',
avatar: editingProfile.avatar || '',
birthday: editingProfile.birthday ? new Date(editingProfile.birthday) : undefined,
command: editingProfile.command || '',
hireDate: editingProfile.hireDate ? new Date(editingProfile.hireDate) : undefined,
relativeHireDate: editingProfile.relativeHireDate ? new Date(editingProfile.relativeHireDate) : undefined,
identity: editingProfile.identity || '',
level: editingProfile.level || '',
levelDate: editingProfile.levelDate ? new Date(editingProfile.levelDate) : undefined,
dutyCode: editingProfile.dutyCode || '',
dutyLevel: editingProfile.dutyLevel?.toString() || '',
dutyName: editingProfile.dutyName || '',
organizationId: editingProfile.organizationId || '',
metadata: {
ethnicity: metadata?.ethnicity || '',
bloodType: metadata?.bloodType || '',
proxyDuty: metadata?.proxyDuty || '',
isRehire: metadata?.isRehire || false,
isExtendedDeparture: metadata?.isExtendedDeparture || false,
positionYear: metadata?.positionYear,
politicalStatus: metadata?.politicalStatus || '',
partyPosition: metadata?.partyPosition || '',
native: {
province: metadata?.native?.province || '',
city: metadata?.native?.city || '',
county: metadata?.native?.county || '',
},
education: metadata?.education || '',
educationForm: metadata?.educationForm || '',
isGraduate: metadata?.isGraduate || false,
schoolMajor: metadata?.schoolMajor || '',
drills: metadata?.drills,
train: metadata?.train || [{ type: '', location: '', major: '' }],
appraisal: metadata?.appraisal || [{ level: '', job: '' }],
foreignLanguage: metadata?.foreignLanguage || '',
reward: metadata?.reward || '',
punish: metadata?.punish || '',
remark: metadata?.remark || '',
},
});
} else if (sheetMode === 'create') {
// 创建模式时重置表单 - 保持与 defaultValues 一致
form.reset({
name: '',
gender: 1,
idNum: '',
paperId: '',
avatar: '',
birthday: undefined,
command: '',
hireDate: undefined,
relativeHireDate: undefined,
identity: '',
level: '',
levelDate: undefined,
dutyCode: '',
dutyLevel: '',
dutyName: '',
organizationId: '',
metadata: {
ethnicity: '',
bloodType: '',
proxyDuty: '',
isRehire: false,
isExtendedDeparture: false,
positionYear: undefined,
politicalStatus: '',
partyPosition: '',
native: {
province: '',
city: '',
county: '',
},
education: '',
educationForm: '',
isGraduate: false,
schoolMajor: '',
drills: undefined,
train: [{ type: '', location: '', major: '' }],
appraisal: [{ level: '', job: '' }],
foreignLanguage: '',
reward: '',
punish: '',
remark: '',
},
});
}
}, [editingProfile, sheetMode, form]);
// 处理 Sheet 开关状态变化
const handleOpenChange = (newOpen: boolean) => {
setIsSheetOpen(newOpen);
// 当 Sheet 关闭时清空表单
if (!newOpen) {
form.reset();
}
};
const handleSubmit = (data: ProfileFormValues) => {
handleSubmitEmployee(data);
setIsSheetOpen(false);
form.reset();
};
const addTrainExperience = () => {
const current = form.getValues('metadata.train') || [];
form.setValue('metadata.train', [...current, { type: '', location: '', major: '' }]);
};
const removeTrainExperience = (index: number) => {
const current = form.getValues('metadata.train') || [];
form.setValue('metadata.train', current.filter((_, i) => i !== index));
};
const addAppraisalExperience = () => {
const current = form.getValues('metadata.appraisal') || [];
form.setValue('metadata.appraisal', [...current, { level: '', job: '' }]);
};
const removeAppraisalExperience = (index: number) => {
const current = form.getValues('metadata.appraisal') || [];
form.setValue('metadata.appraisal', current.filter((_, i) => i !== index));
};
const politicalStatusOptions = Object.values(PoliticalStatus);
const educationFormOptions = Object.values(EducationForm);
const trainTypeOptions = Object.values(TrainType);
const appraisalLevelOptions = Object.values(AppraisalLevel);
const educationOptions = Object.values(Education);
return (
<Sheet open={isSheetOpen} onOpenChange={handleOpenChange}>
<SheetContent side="right" className="w-1/3 min-w-[600px] p-3 overflow-y-auto mb-2">
<SheetHeader>
<SheetTitle>
{sheetMode === 'edit'
? t('profile.profile_sheet.title_edit')
: t('profile.profile_sheet.title_add')
}
</SheetTitle>
<SheetDescription>
{sheetMode === 'edit'
? t('profile.profile_sheet.description_edit')
: t('profile.profile_sheet.description_add')
}{t('profile.profile_sheet.required_fields_note')}
</SheetDescription>
</SheetHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-2">
{/* 基本信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.basic_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 头像和表单字段 */}
<div className="flex gap-4 items-start">
{/* 头像上传区域 - 3:4 长方形 */}
<div className="flex-shrink-0">
<FormField
control={form.control}
name="avatar"
render={({ field }) => (
<FormItem>
<FormControl>
<AvatarUpload
value={field.value}
onChange={field.onChange}
className="w-24 h-32"
placeholder={t('common.upload_avatar')}
accept="image/*"
maxSize={10 * 1024 * 1024} // 10MB
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 表单字段区域 */}
<div className="flex-1 space-y-4">
{/* 姓名和性别 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.name') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.name')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="gender"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.gender') + ' *'}</FormLabel>
<Select
onValueChange={(value) => field.onChange(Number(value))}
value={field.value?.toString() || ''}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.gender')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="1">{t('common.male')}</SelectItem>
<SelectItem value="2">{t('common.female')}</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 身份证号和证件号 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="idNum"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.id_number') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.id_number')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="paperId"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.certificate_number') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.certificate_number')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
</div>
{/* 编制命令 - 占据一整行 */}
<FormField
control={form.control}
name="command"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.formation_command') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.formation_command')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
{/* 组织信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.organization_info')}</CardTitle>
</CardHeader>
<CardContent>
<FormField
control={form.control}
name="organizationId"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.organization') + ' *'}</FormLabel>
<FormControl>
<DeptSelect
value={field.value}
onValueChange={field.onChange}
placeholder={t('profile.profile_sheet.placeholders.organization')}
className="w-full border border-[#EBEFF5]"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
{/* 职务信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.duty_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="dutyName"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.duty_name') + ' *'}</FormLabel>
<FormControl>
<DutySelect
value={field.value}
onChange={field.onChange}
placeholder={t('profile.profile_sheet.placeholders.duty_name')}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dutyCode"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.duty_code')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.duty_code')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dutyLevel"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.duty_level')}</FormLabel>
<FormControl>
<DutyLevelSelect
value={field.value}
onValueChange={field.onChange}
placeholder={t('profile.profile_sheet.duty_level_placeholder')}
className="w-full border border-[#EBEFF5]"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
{/* 身份信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.identity_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="identity"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.identity') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.identity')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="level"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.rank') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.rank')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="levelDate"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{t('profile.profile_sheet.rank_time') + ' *'}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
className={cn(
"w-full pl-3 text-left font-normal border border-[#EBEFF5]",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
dayjs(field.value).format("YYYY-MM-DD")
) : (
<span>{t('common.select_date')}</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
{/* 入职信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.hire_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="hireDate"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{t('profile.profile_sheet.hire_date') + ' *'}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
className={cn(
"w-full pl-3 text-left font-normal border border-[#EBEFF5]",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
dayjs(field.value).format("YYYY-MM-DD")
) : (
<span>{t('common.select_date')}</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="relativeHireDate"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{t('profile.profile_sheet.relative_hire_time')}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
className={cn(
"w-full pl-3 text-left font-normal border border-[#EBEFF5]",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
dayjs(field.value).format("YYYY-MM-DD")
) : (
<span>{t('common.select_date')}</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
{/* 详细信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.detailed_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 基本详细信息 */}
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="metadata.ethnicity"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.ethnicity')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.ethnicity')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="birthday"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.birth_date')}</FormLabel>
<FormControl>
<DateTimePicker
value={field.value}
onChange={field.onChange}
placeholder={t('profile.profile_sheet.placeholders.birth_date')}
showTime={false}
maxDate={new Date()}
minDate={new Date("1900-01-01")}
dateFormat="YYYY-MM-DD"
className='border border-[#EBEFF5]'
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.bloodType"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.blood_type')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full' >
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.blood_type')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="A">{t('profile.profile_sheet.blood_types.a')}</SelectItem>
<SelectItem value="B">{t('profile.profile_sheet.blood_types.b')}</SelectItem>
<SelectItem value="AB">{t('profile.profile_sheet.blood_types.ab')}</SelectItem>
<SelectItem value="O">{t('profile.profile_sheet.blood_types.o')}</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 政治面貌 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="metadata.politicalStatus"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.political_status')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.political_status')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{politicalStatusOptions.map((status) => (
<SelectItem key={status} value={status}>
{status}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.partyPosition"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.party_position')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.party_position')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 籍贯 */}
<div className="space-y-2">
<FormLabel>{t('profile.profile_sheet.native_place')}</FormLabel>
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="metadata.native.province"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder={t('profile.profile_sheet.province')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.native.city"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder={t('profile.profile_sheet.city')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.native.county"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder={t('profile.profile_sheet.county')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
{/* 学历信息 */}
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="metadata.education"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.education')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.education')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{educationOptions.map((education) => (
<SelectItem key={education} value={education}>
{education}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.educationForm"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.education_form')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.education_form')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{educationFormOptions.map((form) => (
<SelectItem key={form} value={form}>
{form}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.schoolMajor"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.school_major')}</FormLabel>
<FormControl className='w-full'>
<Input placeholder={t('profile.profile_sheet.placeholders.school_major')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 其他信息 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="metadata.positionYear"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.position_year')}</FormLabel>
<FormControl>
<Input
type="number"
placeholder={t('profile.profile_sheet.placeholders.position_year')}
{...field}
onChange={(e) => field.onChange(e.target.value ? Number(e.target.value) : undefined)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.foreignLanguage"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.foreign_language')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.foreign_language')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 培训经历 */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<FormLabel>{t('profile.profile_sheet.train_experience')}</FormLabel>
<Button className='border border-[#5D6E89]' type="button" variant="outline" size="sm" onClick={addTrainExperience}>
<Plus className="w-4 h-4 mr-2" />
{t('profile.profile_sheet.add_train')}
</Button>
</div>
{form.watch('metadata.train')?.map((_, index) => (
<Card key={index} className="p-4">
<div className="flex items-center justify-between mb-4">
<h4 className="text-sm font-medium">{t('profile.profile_sheet.train_experience')} {index + 1}</h4>
{index > 0 && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => removeTrainExperience(index)}
>
<Trash2 className="w-4 h-4" />
</Button>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name={`metadata.train.${index}.type`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.train_type')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.train_type')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{trainTypeOptions.map((type) => (
<SelectItem key={type} value={type}>
{type}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`metadata.train.${index}.location`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.train_location')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.train_location')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name={`metadata.train.${index}.major`}
render={({ field }) => (
<FormItem className="mt-4">
<FormLabel>{t('profile.profile_sheet.train_major')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.train_major')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</Card>
))}
</div>
{/* 考核经历 */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<FormLabel>{t('profile.profile_sheet.appraisal_experience')}</FormLabel>
<Button className='border border-[#5D6E89]' type="button" variant="outline" size="sm" onClick={addAppraisalExperience}>
<Plus className="w-4 h-4 mr-2" />
{t('profile.profile_sheet.add_appraisal')}
</Button>
</div>
{form.watch('metadata.appraisal')?.map((_, index) => (
<Card key={index} className="p-4">
<div className="flex items-center justify-between mb-4">
<h4 className="text-sm font-medium">{t('profile.profile_sheet.appraisal_experience')} {index + 1}</h4>
{index > 0 && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => removeAppraisalExperience(index)}
>
<Trash2 className="w-4 h-4" />
</Button>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name={`metadata.appraisal.${index}.level`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.appraisal_level')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.appraisal_level')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{appraisalLevelOptions.map((level) => (
<SelectItem key={level} value={level}>
{level}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`metadata.appraisal.${index}.job`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.appraisal_job')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.appraisal_job')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</Card>
))}
</div>
{/* 奖励 - 独占一行 */}
<FormField
control={form.control}
name="metadata.reward"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.reward')}</FormLabel>
<FormControl>
<Textarea placeholder={t('profile.profile_sheet.placeholders.reward')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* 处分 - 独占一行 */}
<FormField
control={form.control}
name="metadata.punish"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.punish')}</FormLabel>
<FormControl>
<Textarea placeholder={t('profile.profile_sheet.placeholders.punish')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.remark"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.remark')}</FormLabel>
<FormControl>
<Textarea placeholder={t('profile.profile_sheet.placeholders.remark')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
<SheetFooter className="gap-2">
<Button type="submit">
{t('common.confirm')}
</Button>
</SheetFooter>
</form>
</Form>
</SheetContent>
</Sheet>
);
}