siakad-itm/resources/js/pages/admin/users/administrators/create.tsx
Yoga Pangestu 2885de2c20 feat: add lecturer and student management pages with CRUD functionality
- Implemented LecturerEdit and LecturerIndex components for managing lecturers.
- Created StudentCreate and StudentEdit components for adding and editing students.
- Developed StudentIndex component for listing students with search and pagination.
- Added department and user types for better type safety.
- Updated routes for lecturers and students, including reset password functionality.
- Removed AppSidebar from dashboard for a cleaner layout.
2026-08-21 14:14:01 +07:00

161 lines
9.3 KiB
TypeScript

import { DatePicker } from '@/components/date-picker';
import InputError from '@/components/input-error';
import { PageHeader } from '@/components/page-header';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Combobox, ComboboxContent, ComboboxInput, ComboboxItem, ComboboxList } from '@/components/ui/combobox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { PhoneInput } from '@/components/ui/phone-input';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Textarea } from '@/components/ui/textarea';
import { index, store } from '@/routes/admin/users/administrators';
import { Form, Head } from '@inertiajs/react';
import { format } from 'date-fns';
import { useState } from 'react';
type Role = { id: number; name: string };
type Props = {
roles: Role[];
};
export default function AdministratorCreate({ roles }: Props) {
const [gender, setGender] = useState('');
const [birthDate, setBirthDate] = useState<Date | undefined>();
const [role, setRole] = useState('');
return (
<>
<Head title="Tambah Administrator" />
<div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
<PageHeader
title="Tambah Administrator"
actions={
<Button variant="outline" asChild>
<a href={index.url()}>Kembali</a>
</Button>
}
/>
<Form action={store()} className="space-y-6">
{({ errors, processing }) => (
<>
<Card>
<CardHeader>
<CardTitle>Informasi Akun</CardTitle>
</CardHeader>
<CardContent className="grid gap-4 md:grid-cols-3">
<div className="grid gap-2">
<Label htmlFor="username">
Username <span className="text-red-500">*</span>
</Label>
<Input id="username" name="username" placeholder="Masukkan username" />
<InputError message={errors.username} />
</div>
<div className="grid gap-2">
<Label htmlFor="email">
Email <span className="text-red-500">*</span>
</Label>
<Input id="email" name="email" type="email" placeholder="Masukkan email" />
<InputError message={errors.email} />
</div>
<div className="grid gap-2">
<Label>
Role <span className="text-red-500">*</span>
</Label>
<input type="hidden" name="role" value={role} />
<Combobox value={role} onValueChange={(v) => setRole(v ?? '')}>
<ComboboxInput placeholder="Pilih role" className="w-full" />
<ComboboxContent>
<ComboboxList>
{roles.map((r) => (
<ComboboxItem key={r.id} value={r.name}>
{r.name}
</ComboboxItem>
))}
</ComboboxList>
</ComboboxContent>
</Combobox>
<InputError message={errors.role} />
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Profil Pribadi</CardTitle>
</CardHeader>
<CardContent className="grid gap-4 md:grid-cols-2">
<div className="grid gap-2">
<Label htmlFor="full_name">
Nama Lengkap <span className="text-red-500">*</span>
</Label>
<Input id="full_name" name="full_name" placeholder="Masukkan nama lengkap" />
<InputError message={errors.full_name} />
</div>
<div className="grid gap-2">
<Label htmlFor="phone_number">
Nomor Telepon <span className="text-red-500">*</span>
</Label>
<PhoneInput id="phone_number" name="phone_number" placeholder="08xx xxxx xxxx" />
<InputError message={errors.phone_number} />
</div>
<div className="grid gap-4 md:col-span-2 md:grid-cols-3">
<div className="grid gap-2">
<Label>
Jenis Kelamin <span className="text-red-500">*</span>
</Label>
<input type="hidden" name="gender" value={gender} />
<RadioGroup value={gender} onValueChange={setGender} className="flex gap-4">
<div className="flex items-center gap-2">
<RadioGroupItem value="male" id="male" />
<Label htmlFor="male" className="font-normal">Laki-laki</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="female" id="female" />
<Label htmlFor="female" className="font-normal">Perempuan</Label>
</div>
</RadioGroup>
<InputError message={errors.gender} />
</div>
<div className="grid gap-2">
<Label>
Tempat Lahir <span className="text-red-500">*</span>
</Label>
<Input name="birth_place" placeholder="Masukkan tempat lahir" />
<InputError message={errors.birth_place} />
</div>
<div className="grid gap-2">
<Label>
Tanggal Lahir <span className="text-red-500">*</span>
</Label>
<input type="hidden" name="birth_date" value={birthDate ? format(birthDate, 'yyyy-MM-dd') : ''} />
<DatePicker value={birthDate} onChange={setBirthDate} />
<InputError message={errors.birth_date} />
</div>
</div>
<div className="grid gap-2 md:col-span-2">
<Label htmlFor="address">
Alamat <span className="text-red-500">*</span>
</Label>
<Textarea id="address" name="address" placeholder="Masukkan alamat" />
<InputError message={errors.address} />
</div>
</CardContent>
</Card>
<div className="flex justify-end">
<Button type="submit" disabled={processing}>
Simpan
</Button>
</div>
</>
)}
</Form>
</div>
</>
);
}