189 lines
8.7 KiB
TypeScript
189 lines
8.7 KiB
TypeScript
import { Head, Link, useForm } 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 Employee {
|
|
id: number;
|
|
name: string;
|
|
nip: string;
|
|
department: string | null;
|
|
}
|
|
|
|
interface PageProps {
|
|
employees: Employee[];
|
|
}
|
|
|
|
export default function Create({ employees }: PageProps) {
|
|
const { data, setData, post, processing, errors } = useForm({
|
|
employee_id: '',
|
|
date: '',
|
|
shift: '',
|
|
status: 'hadir',
|
|
check_in: '',
|
|
check_out: '',
|
|
notes: '',
|
|
});
|
|
|
|
const selectedEmployee = employees.find((employee) => String(employee.id) === data.employee_id) ?? null;
|
|
|
|
const submit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
post('/admin/attendance', {
|
|
transform: (formData) => ({
|
|
...formData,
|
|
check_in: formData.check_in || null,
|
|
check_out: formData.check_out || null,
|
|
notes: formData.notes || null,
|
|
}),
|
|
});
|
|
};
|
|
|
|
return (
|
|
<AppLayout>
|
|
<Head title="Input Absensi" />
|
|
|
|
<div className="p-4 md:p-8 max-w-3xl mx-auto">
|
|
<Button variant="outline" asChild className="mb-6">
|
|
<Link href="/admin/attendance">Kembali</Link>
|
|
</Button>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Input Absensi Karyawan</CardTitle>
|
|
<p className="text-sm text-muted-foreground">Isi data absensi harian untuk 1 karyawan per tanggal.</p>
|
|
</CardHeader>
|
|
|
|
<Separator />
|
|
|
|
<CardContent className="pt-6">
|
|
<form onSubmit={submit} className="space-y-6">
|
|
<div className="space-y-2">
|
|
<Label>Karyawan</Label>
|
|
<Select value={data.employee_id} onValueChange={(value) => setData('employee_id', value)}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Pilih karyawan" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{employees.map((employee) => (
|
|
<SelectItem key={employee.id} value={String(employee.id)}>
|
|
{employee.name} ({employee.nip})
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.employee_id && <p className="text-xs text-red-500">{errors.employee_id}</p>}
|
|
</div>
|
|
|
|
{selectedEmployee && (
|
|
<div className="rounded-md border bg-muted/40 px-4 py-3 text-sm">
|
|
<span className="text-muted-foreground">Departemen: </span>
|
|
<span className="font-medium">{selectedEmployee.department || '-'}</span>
|
|
</div>
|
|
)}
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>Tanggal</Label>
|
|
<Input
|
|
type="date"
|
|
value={data.date}
|
|
onChange={(e) => setData('date', e.target.value)}
|
|
/>
|
|
{errors.date && <p className="text-xs text-red-500">{errors.date}</p>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Shift</Label>
|
|
<Select value={data.shift} onValueChange={(value) => setData('shift', value)}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Pilih shift" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="Pagi">Pagi</SelectItem>
|
|
<SelectItem value="Siang">Siang</SelectItem>
|
|
<SelectItem value="Malam">Malam</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.shift && <p className="text-xs text-red-500">{errors.shift}</p>}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>Jam Masuk</Label>
|
|
<Input
|
|
type="datetime-local"
|
|
value={data.check_in}
|
|
onChange={(e) => setData('check_in', e.target.value)}
|
|
/>
|
|
{errors.check_in && <p className="text-xs text-red-500">{errors.check_in}</p>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Jam Pulang</Label>
|
|
<Input
|
|
type="datetime-local"
|
|
value={data.check_out}
|
|
onChange={(e) => setData('check_out', e.target.value)}
|
|
/>
|
|
{errors.check_out && <p className="text-xs text-red-500">{errors.check_out}</p>}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Status</Label>
|
|
<Select value={data.status} onValueChange={(value) => setData('status', value)}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Pilih status" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="hadir">Hadir</SelectItem>
|
|
<SelectItem value="izin">Izin</SelectItem>
|
|
<SelectItem value="sakit">Sakit</SelectItem>
|
|
<SelectItem value="alpha">Alpha</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
{errors.status && <p className="text-xs text-red-500">{errors.status}</p>}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Catatan</Label>
|
|
<Input
|
|
value={data.notes}
|
|
onChange={(e) => setData('notes', e.target.value)}
|
|
placeholder="Opsional"
|
|
/>
|
|
{errors.notes && <p className="text-xs text-red-500">{errors.notes}</p>}
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
<div className="flex gap-3">
|
|
<Button type="submit" disabled={processing}>
|
|
{processing ? 'Menyimpan...' : 'Simpan Absensi'}
|
|
</Button>
|
|
<Button type="button" variant="ghost" asChild>
|
|
<Link href="/admin/attendance">Batal</Link>
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</AppLayout>
|
|
);
|
|
}
|