224 lines
12 KiB
TypeScript
224 lines
12 KiB
TypeScript
import ProfileController from '@/actions/App/Http/Controllers/Settings/ProfileController';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Calendar } from "@/components/ui/calendar";
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Field, FieldError } from "@/components/ui/field";
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import {
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger,
|
|
} from "@/components/ui/popover";
|
|
import { Textarea } from '@/components/ui/textarea';
|
|
import { edit } from '@/routes/profile';
|
|
import { Head, useForm, usePage } from '@inertiajs/react';
|
|
import { Loader, Save } from 'lucide-react';
|
|
import React from 'react';
|
|
import { toast } from 'sonner';
|
|
|
|
export default function Profile({
|
|
status,
|
|
}: {
|
|
status?: string;
|
|
}) {
|
|
const { auth } = usePage().props;
|
|
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
|
|
|
|
const { data, setData, patch, processing, errors } = useForm({
|
|
nik: auth.user.profile?.nik || '',
|
|
full_name: auth.user.profile?.full_name || '',
|
|
email: auth.user.email || '',
|
|
username: auth.user.username || '',
|
|
phone_number: auth.user.profile?.phone_number || '',
|
|
birth_place: auth.user.profile?.birth_place || '',
|
|
birth_date: auth.user.profile?.birth_date || '',
|
|
address: auth.user.profile?.address || '',
|
|
});
|
|
|
|
const onSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
patch(ProfileController.update().url, {
|
|
preserveScroll: true,
|
|
onSuccess: (response: any) => {
|
|
toast.success(response.props.flash.success || 'Profil berhasil diperbarui.');
|
|
},
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col gap-6">
|
|
<Head title="Profil" />
|
|
|
|
<h1 className="sr-only">Profil</h1>
|
|
|
|
<form onSubmit={onSubmit} className="space-y-6">
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<div className="lg:col-span-2 space-y-6">
|
|
<Card className="overflow-hidden border-none shadow-lg bg-card/50 backdrop-blur-sm">
|
|
<CardHeader className="border-b">
|
|
<CardTitle>Informasi Personal</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<Field>
|
|
<Label htmlFor="nik" required>NIK</Label>
|
|
<Input
|
|
id="nik"
|
|
value={data.nik}
|
|
onChange={(e) => setData('nik', e.target.value)}
|
|
placeholder="Contoh: 3213051307900001"
|
|
maxLength={16}
|
|
autoComplete="off"
|
|
/>
|
|
<FieldError error={errors.nik} label="NIK" className="text-xs" />
|
|
</Field>
|
|
|
|
<Field>
|
|
<Label htmlFor="full_name" required>Nama Lengkap</Label>
|
|
<Input
|
|
id="full_name"
|
|
value={data.full_name}
|
|
onChange={(e) => setData('full_name', e.target.value)}
|
|
placeholder="Nama Lengkap"
|
|
autoComplete="off"
|
|
/>
|
|
<FieldError error={errors.full_name} label="Nama Lengkap" className="text-xs" />
|
|
</Field>
|
|
|
|
<Field>
|
|
<Label htmlFor="phone_number" required>Nomor Telepon</Label>
|
|
<Input
|
|
id="phone_number"
|
|
value={data.phone_number}
|
|
onChange={(e) => setData('phone_number', e.target.value)}
|
|
placeholder="Nomor Telepon"
|
|
autoComplete="off"
|
|
/>
|
|
<FieldError error={errors.phone_number} label="Nomor Telepon" className="text-xs" />
|
|
</Field>
|
|
|
|
<Field>
|
|
<Label htmlFor="birth_place" required>Tempat Lahir</Label>
|
|
<Input
|
|
id="birth_place"
|
|
value={data.birth_place}
|
|
onChange={(e) => setData('birth_place', e.target.value)}
|
|
placeholder="Tempat Lahir"
|
|
autoComplete="off"
|
|
/>
|
|
<FieldError error={errors.birth_place} label="Tempat Lahir" className="text-xs" />
|
|
</Field>
|
|
|
|
<Field>
|
|
<Label htmlFor="birth_date" required>Tanggal Lahir</Label>
|
|
<Popover open={isCalendarOpen} onOpenChange={setIsCalendarOpen}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
variant="outline"
|
|
id="birth_date"
|
|
className="w-full justify-start font-normal"
|
|
>
|
|
{data.birth_date ? (
|
|
new Intl.DateTimeFormat("id-ID", {
|
|
day: "numeric",
|
|
month: "long",
|
|
year: "numeric",
|
|
}).format(new Date(data.birth_date))
|
|
) : (
|
|
<span className="text-muted-foreground">Pilih Tanggal</span>
|
|
)}
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
|
|
<Calendar
|
|
mode="single"
|
|
selected={data.birth_date ? new Date(data.birth_date) : undefined}
|
|
defaultMonth={data.birth_date ? new Date(data.birth_date) : new Date(2000, 0, 1)}
|
|
captionLayout="dropdown"
|
|
onSelect={(selectedDate: Date | undefined) => {
|
|
if (selectedDate) {
|
|
setData('birth_date', selectedDate.getFullYear() + "-" + String(selectedDate.getMonth() + 1).padStart(2, '0') + "-" + String(selectedDate.getDate()).padStart(2, '0'));
|
|
} else {
|
|
setData('birth_date', '');
|
|
}
|
|
|
|
setIsCalendarOpen(false);
|
|
}}
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
<FieldError error={errors.birth_date} label="Tanggal Lahir" className="text-xs" />
|
|
</Field>
|
|
</div>
|
|
|
|
<Field>
|
|
<Label htmlFor="address" required>Alamat</Label>
|
|
<Textarea
|
|
id="address"
|
|
value={data.address}
|
|
onChange={(e) => setData('address', e.target.value)}
|
|
placeholder="Alamat Lengkap"
|
|
rows={3}
|
|
/>
|
|
<FieldError error={errors.address} label="Alamat" className="text-xs" />
|
|
</Field>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
<Card className="overflow-hidden border-none shadow-lg bg-card/50 backdrop-blur-sm">
|
|
<CardHeader className="border-b">
|
|
<CardTitle>Kredensial Akun</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-6">
|
|
<Field>
|
|
<Label htmlFor="email" required>Alamat Email</Label>
|
|
<Input
|
|
id="email"
|
|
type="email"
|
|
value={data.email}
|
|
onChange={(e) => setData('email', e.target.value)}
|
|
autoComplete="off"
|
|
placeholder="Alamat Email"
|
|
/>
|
|
<FieldError error={errors.email} label="Alamat Email" className="text-xs" />
|
|
</Field>
|
|
|
|
<Field>
|
|
<Label htmlFor="username" required>Nama Pengguna</Label>
|
|
<Input
|
|
id="username"
|
|
value={data.username}
|
|
onChange={(e) => setData('username', e.target.value)}
|
|
placeholder="Username"
|
|
autoComplete="off"
|
|
/>
|
|
<FieldError error={errors.username} label="Nama Pengguna" className="text-xs" />
|
|
</Field>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
|
<Button type="submit" className="w-full" disabled={processing}>
|
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
Profile.layout = {
|
|
breadcrumbs: [
|
|
{
|
|
title: 'Pengaturan Profil',
|
|
href: edit(),
|
|
},
|
|
],
|
|
};
|