239 lines
14 KiB
TypeScript
239 lines
14 KiB
TypeScript
import { Head, useForm, Link } from '@inertiajs/react';
|
|
import React from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
import { Separator } from '@/components/ui/separator';
|
|
import AppLayout from '@/layouts/app-layout';
|
|
|
|
interface PageProps {
|
|
departments: { id: number; name: string }[];
|
|
positions: { id: number; name: string }[];
|
|
errors: Partial<Record<string, string>>;
|
|
}
|
|
|
|
export default function Create({ departments, positions }: PageProps) {
|
|
const { data, setData, post, processing, errors } = useForm({
|
|
name: '',
|
|
email: '',
|
|
nip: '',
|
|
gender: '',
|
|
birth_date: '',
|
|
place_of_birth: '',
|
|
address: '',
|
|
phone_number: '',
|
|
department_id: '',
|
|
position_id: '',
|
|
status: '',
|
|
join_date: '',
|
|
});
|
|
|
|
const submit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
post('/admin/employees');
|
|
};
|
|
|
|
return (
|
|
<AppLayout>
|
|
<Head title="Tambah Karyawan Baru" />
|
|
|
|
<div className="p-4 md:p-8 max-w-5xl mx-auto">
|
|
<Button variant="outline" asChild className="mb-6">
|
|
<Link href="/admin/employees">← Kembali</Link>
|
|
</Button>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Form Data Karyawan</CardTitle>
|
|
<p className="text-sm text-muted-foreground">Lengkapi form di bawah ini untuk menambahkan karyawan baru.</p>
|
|
</CardHeader>
|
|
<Separator />
|
|
<CardContent className="pt-6">
|
|
<form onSubmit={submit} className="space-y-8">
|
|
|
|
{/* INFORMASI PRIBADI */}
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium flex items-center gap-2">
|
|
<span className="bg-primary/10 text-primary w-6 h-6 rounded-full flex items-center justify-center text-xs">1</span>
|
|
Informasi Pribadi
|
|
</h3>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
{/* Kolom Kiri */}
|
|
<div className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>Nama Lengkap</Label>
|
|
<Input
|
|
placeholder="Nama sesuai KTP"
|
|
value={data.name}
|
|
onChange={e => setData('name', e.target.value)}
|
|
/>
|
|
{errors.name && <div className="text-red-500 text-xs">{errors.name}</div>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Email</Label>
|
|
<Input
|
|
type="email"
|
|
value={data.email}
|
|
onChange={e => setData('email', e.target.value)}
|
|
/>
|
|
{errors.email && <div className="text-red-500 text-xs">{errors.email}</div>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>No. Telepon</Label>
|
|
<Input
|
|
value={data.phone_number}
|
|
onChange={e => setData('phone_number', e.target.value)}
|
|
/>
|
|
{errors.phone_number && <div className="text-red-500 text-xs">{errors.phone_number}</div>}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Kolom Kanan */}
|
|
<div className="space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>Tempat Lahir</Label>
|
|
<Input
|
|
value={data.place_of_birth}
|
|
onChange={e => setData('place_of_birth', e.target.value)}
|
|
/>
|
|
{errors.place_of_birth && <div className="text-red-500 text-xs">{errors.place_of_birth}</div>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>Tanggal Lahir</Label>
|
|
<Input
|
|
type="date"
|
|
value={data.birth_date}
|
|
onChange={e => setData('birth_date', e.target.value)}
|
|
/>
|
|
{errors.birth_date && <div className="text-red-500 text-xs">{errors.birth_date}</div>}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Jenis Kelamin</Label>
|
|
<Select onValueChange={(val) => setData('gender', val)}>
|
|
<SelectTrigger><SelectValue placeholder="Pilih Gender" /></SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="L">Laki-laki</SelectItem>
|
|
<SelectItem value="P">Perempuan</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.gender && <div className="text-red-500 text-xs">{errors.gender}</div>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Alamat Lengkap</Label>
|
|
<Input
|
|
value={data.address}
|
|
onChange={e => setData('address', e.target.value)}
|
|
/>
|
|
{errors.address && <div className="text-red-500 text-xs">{errors.address}</div>}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* DATA KEPEGAWAIAN */}
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium flex items-center gap-2">
|
|
<span className="bg-primary/10 text-primary w-6 h-6 rounded-full flex items-center justify-center text-xs">2</span>
|
|
Data Kepegawaian
|
|
</h3>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
{/* Kolom Kiri */}
|
|
<div className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>Nomor Induk (NIP)</Label>
|
|
<Input
|
|
placeholder="Contoh: 2024001"
|
|
value={data.nip}
|
|
onChange={e => setData('nip', e.target.value)}
|
|
/>
|
|
{errors.nip && <div className="text-red-500 text-xs">{errors.nip}</div>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Departemen</Label>
|
|
<Select onValueChange={(val) => setData('department_id', val)}>
|
|
<SelectTrigger><SelectValue placeholder="Pilih Departemen" /></SelectTrigger>
|
|
<SelectContent>
|
|
{departments.map((dept) => (
|
|
<SelectItem key={dept.id} value={String(dept.id)}>{dept.name}</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.department_id && <div className="text-red-500 text-xs">Wajib diisi</div>}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Kolom Kanan */}
|
|
<div className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>Jabatan</Label>
|
|
<Select onValueChange={(val) => setData('position_id', val)}>
|
|
<SelectTrigger><SelectValue placeholder="Pilih Jabatan" /></SelectTrigger>
|
|
<SelectContent>
|
|
{positions.map((pos) => (
|
|
<SelectItem key={pos.id} value={String(pos.id)}>{pos.name}</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.position_id && <div className="text-red-500 text-xs">Wajib diisi</div>}
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>Status</Label>
|
|
<Select onValueChange={(val) => setData('status', val)}>
|
|
<SelectTrigger><SelectValue placeholder="Pilih Status" /></SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="PKWT">PKWT (Kontrak)</SelectItem>
|
|
<SelectItem value="PKWTT">PKWTT (Tetap)</SelectItem>
|
|
<SelectItem value="Magang">Magang</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.status && <div className="text-red-500 text-xs">{errors.status}</div>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Tanggal Masuk</Label>
|
|
<Input
|
|
type="date"
|
|
value={data.join_date}
|
|
onChange={e => setData('join_date', e.target.value)}
|
|
/>
|
|
{errors.join_date && <div className="text-red-500 text-xs">{errors.join_date}</div>}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* TOMBOL AKSI */}
|
|
<div className="flex justify-end gap-4 pt-2">
|
|
<Button type="button" variant="ghost" asChild>
|
|
<Link href="/admin/employees">Batal</Link>
|
|
</Button>
|
|
<Button type="submit" disabled={processing} className="px-8">
|
|
{processing ? 'Menyimpan...' : 'Simpan Data'}
|
|
</Button>
|
|
</div>
|
|
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</AppLayout>
|
|
);
|
|
} |